UNPKG

@rxap/authentication

Version:

Provides authentication services, guards, and interceptors for Angular applications. It supports token-based authentication and provides features such as sign-out functionality and routing based on authentication status. This package also includes utiliti

310 lines (297 loc) 13.8 kB
import * as i0 from '@angular/core'; import { InjectionToken, inject, Injectable, Inject, Optional, EventEmitter, Directive, Output, HostListener } from '@angular/core'; import * as i1 from '@angular/router'; import { Router } from '@angular/router'; import { BehaviorSubject, ReplaySubject, take, switchMap, of, EMPTY } from 'rxjs'; import { tap } from 'rxjs/operators'; const RXAP_AUTHENTICATION_DEACTIVATED = new InjectionToken('rxap/authentication/deactivated'); const RXAP_AUTHENTICATION_ACCESS_TOKEN = new InjectionToken('rxap/authentication/access-token', { providedIn: 'root', factory: () => new BehaviorSubject(null), }); const RXAP_INITIAL_AUTHENTICATION_STATE = new InjectionToken('rxap/authentication/initial-state', { providedIn: 'root', factory: () => false, }); function withDisabledAuthentication(disabled = true) { return { provide: RXAP_AUTHENTICATION_DEACTIVATED, useValue: disabled, }; } var AuthenticationEventType; (function (AuthenticationEventType) { AuthenticationEventType["OnAuthSuccess"] = "on-auth-success"; AuthenticationEventType["OnAuthError"] = "on-auth-error"; AuthenticationEventType["OnLogout"] = "on-logout"; })(AuthenticationEventType || (AuthenticationEventType = {})); class RxapAuthenticationService { constructor() { this.isAuthenticated$ = new BehaviorSubject(null); this.events$ = new ReplaySubject(); this._authenticated = inject(RXAP_INITIAL_AUTHENTICATION_STATE); this.isAuthenticated().then(isAuthenticated => this.isAuthenticated$.next(isAuthenticated)); } async signOut() { this._authenticated = false; this.isAuthenticated$.next(this._authenticated); this.events$.next({ type: AuthenticationEventType.OnLogout }); } isAuthenticated() { return Promise.resolve(this._authenticated); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); class AuthenticationRoutingService { constructor(router, authenticationService, deactivated = null) { this.router = router; this.authenticationService = authenticationService; this.deactivated = deactivated; if (!deactivated) { console.log('Authentication is enabled'); this.authenticationService.isAuthenticated$.pipe(tap(isAuthenticated => { if (isAuthenticated) { return this.router.navigate(['/']); } else { return this.router.navigate(['/', 'authentication', 'login']); } })).subscribe(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AuthenticationRoutingService, deps: [{ token: Router }, { token: RxapAuthenticationService }, { token: RXAP_AUTHENTICATION_DEACTIVATED, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AuthenticationRoutingService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: AuthenticationRoutingService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [{ type: i1.Router, decorators: [{ type: Inject, args: [Router] }] }, { type: RxapAuthenticationService, decorators: [{ type: Inject, args: [RxapAuthenticationService] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_AUTHENTICATION_DEACTIVATED] }] }] }); class RxapAuthenticationGuard { constructor(authentication, router, deactivated = null) { this.authentication = authentication; this.router = router; this.deactivated = deactivated; this.lastUrl = null; } canActivate(route, state) { console.debug('[RxapAuthenticationGuard] can activate', state.url); return this.checkAuthStatus(route, state); } canActivateChild(childRoute, state) { console.debug('[RxapAuthenticationGuard] can activate child', state.url); return this.checkAuthStatus(childRoute, state); } async checkAuthStatus(route, state) { if (this.deactivated) { return true; } const authenticated = await this.authentication.isAuthenticated(); if (authenticated === null) { if (!this.lastUrl || (state.url !== '/' && !state.url.match(/authentication\/login/))) { this.lastUrl = state.url; } return this.router.createUrlTree(['/', 'authentication', 'loading']); } if (authenticated) { if (this.lastUrl && (state.url /*?*/ === '/' || state.url.match(/authentication\/login/))) { const lastUrl = this.lastUrl; this.lastUrl = null; return this.createUrlTreeToLastUrl(lastUrl); } else { if (state.url.match(/authentication/)) { if (state.url.match(/authentication\/reset-password/)) { return true; } return this.router.createUrlTree(['/']); } else { this.lastUrl = null; return true; } } } else { if (!state.url.match(/^\/?authentication/)) { this.lastUrl = state.url; } if (state.url.match(/^\/?authentication/)) { if (this.lastUrl && this.lastUrl.match(/^\/?authentication/)) { const lastUrl = this.lastUrl; this.lastUrl = null; return this.createUrlTreeToLastUrl(lastUrl); } return true; } else { return this.router.createUrlTree(['/', 'authentication', 'login']); } } } createUrlTreeToLastUrl(lastUrl) { const urlMatch = lastUrl.match(/^([^?#]+)(\?([^#]+))?(#(.+))?$/); if (urlMatch) { let queryParams = {}; if (urlMatch[3]) { const queryParamsString = urlMatch[3]; queryParams = queryParamsString.split('&').map(param => { const split = param.split('='); return { [split[0]]: split[1] }; }).reduce((params, param) => ({ ...params, ...param }), {}); } let fragment = undefined; if (urlMatch[5]) { fragment = urlMatch[5]; } return this.router.createUrlTree([urlMatch[1]], { queryParams, fragment, }); } return this.router.createUrlTree([lastUrl]); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationGuard, deps: [{ token: RxapAuthenticationService }, { token: Router }, { token: RXAP_AUTHENTICATION_DEACTIVATED, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationGuard, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RxapAuthenticationGuard, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: RxapAuthenticationService, decorators: [{ type: Inject, args: [RxapAuthenticationService] }] }, { type: i1.Router, decorators: [{ type: Inject, args: [Router] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [RXAP_AUTHENTICATION_DEACTIVATED] }] }] }); function BearerTokenInterceptor(req, next) { const accessToken$ = inject(RXAP_AUTHENTICATION_ACCESS_TOKEN); if (req.url.match(/https?:\/\/[^/]+\/api/)) { return accessToken$.pipe(take(1), switchMap(accessToken => { if (accessToken && (accessToken.valid === undefined || accessToken.valid)) { console.debug('Add access token to request', req.url); return next(req.clone({ setHeaders: { Authorization: `Bearer ${accessToken.token}`, }, })); } else { console.debug('No valid access token found!', req.url); } return next(req); })); } else { console.debug('Skip adding access token to request', req.url); } return next(req); } class DisabledAuthenticationService { constructor() { this.isAuthenticated$ = of(true); this.events$ = EMPTY; } async signOut() { console.log('Authentication is disabled. No sign out possible'); } async isAuthenticated() { return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DisabledAuthenticationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DisabledAuthenticationService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DisabledAuthenticationService, decorators: [{ type: Injectable }] }); function provideAuthentication(service, ...additionalProviders) { return [ { provide: RxapAuthenticationService, useClass: service, }, ...additionalProviders, ]; } function withInitialAuthenticationState(state) { return { provide: RXAP_INITIAL_AUTHENTICATION_STATE, useValue: state, }; } /* ignore coverage */ class RegisterService { constructor() { console.warn('The default RegisterService implementation should only be used in a development environment!'); } register(email, password) { return Promise.resolve(true); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RegisterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RegisterService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RegisterService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); class SignOutDirective { constructor(auth) { this.auth = auth; this.successful = new EventEmitter(); this.failure = new EventEmitter(); } async onClick() { try { await this.auth.signOut(); this.successful.emit(); } catch (e) { this.failure.emit(e); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: SignOutDirective, deps: [{ token: RxapAuthenticationService }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.1", type: SignOutDirective, isStandalone: true, selector: "[rxapSignOut]", outputs: { successful: "successful", failure: "failure" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: SignOutDirective, decorators: [{ type: Directive, args: [{ selector: '[rxapSignOut]', standalone: true, }] }], ctorParameters: () => [{ type: RxapAuthenticationService }], propDecorators: { successful: [{ type: Output }], failure: [{ type: Output }], onClick: [{ type: HostListener, args: ['click'] }] } }); // region // endregion /** * Generated bundle index. Do not edit. */ export { AuthenticationEventType, AuthenticationRoutingService, BearerTokenInterceptor, DisabledAuthenticationService, RXAP_AUTHENTICATION_ACCESS_TOKEN, RXAP_AUTHENTICATION_DEACTIVATED, RXAP_INITIAL_AUTHENTICATION_STATE, RegisterService, RxapAuthenticationGuard, RxapAuthenticationService, SignOutDirective, provideAuthentication, withDisabledAuthentication, withInitialAuthenticationState }; //# sourceMappingURL=rxap-authentication.mjs.map