@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
JavaScript
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