UNPKG

@idea-ionic/auth0

Version:
183 lines (177 loc) 7.42 kB
import * as i0 from '@angular/core'; import { APP_INITIALIZER, NgModule, inject, Injectable } from '@angular/core'; import * as i1 from '@auth0/auth0-angular'; import { AuthModule, AuthClientConfig, AuthService } from '@auth0/auth0-angular'; import { IDEAEnvironment, IDEAApiService } from '@idea-ionic/common'; import { firstValueFrom } from 'rxjs'; import { Platform } from '@ionic/angular/standalone'; import { Browser } from '@capacitor/browser'; import { Auth0User } from 'idea-toolbox'; const injectConfig = (env, config) => { return () => config.set({ domain: env.auth0.domain, clientId: env.auth0.clientId, useRefreshTokens: env.auth0.storeRefreshToken, cacheLocation: env.auth0.storeRefreshToken ? 'localstorage' : 'memory', authorizationParams: { redirect_uri: env.auth0.callbackUri || window.location.origin } }); }; class IDEAAuth0Module { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Module, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Module, imports: [i1.AuthModule] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Module, providers: [ { provide: APP_INITIALIZER, useFactory: injectConfig, deps: [IDEAEnvironment, AuthClientConfig], multi: true } ], imports: [AuthModule.forRoot()] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Module, decorators: [{ type: NgModule, args: [{ imports: [AuthModule.forRoot()], providers: [ { provide: APP_INITIALIZER, useFactory: injectConfig, deps: [IDEAEnvironment, AuthClientConfig], multi: true } ] }] }] }); class IDEAAuth0Service { constructor() { this._env = inject(IDEAEnvironment); this._platform = inject(Platform); this._auth0 = inject(AuthService); } /** * The internal Auth0's service. */ get __raw() { return this._auth0; } isMobileDevice() { return this._platform.is('capacitor'); } /** * Open (if needed) Auth0's Universal Login page, to authenticate a user. * @param afterRedirectTo where to go after a successful login */ goToLogin(afterRedirectTo) { this.isMobileDevice() ? this.loginWithMobile(afterRedirectTo) : this.loginWithSPA(afterRedirectTo); } async loginWithSPA(afterRedirectTo) { await firstValueFrom(this._auth0.loginWithRedirect({ appState: { target: afterRedirectTo } })); } async loginWithMobile(afterRedirectTo) { await firstValueFrom(this._auth0.loginWithRedirect({ appState: { target: afterRedirectTo }, openUrl: url => Browser.open({ url }) })); } /** * Open (if needed) Auth0's Universal Login page, to logout a user. */ goToLogout() { this.isMobileDevice() ? this.logoutWithMobile() : this.logoutWithSPA(); } async logoutWithSPA() { await firstValueFrom(this._auth0.logout({ logoutParams: { returnTo: document.location.origin } })); } async logoutWithMobile() { await firstValueFrom(this._auth0.logout({ logoutParams: { localOnly: true }, openUrl: url => Browser.open({ url }) })); } /** * Handle the callback after a login or logout in Auth0 Universal Login page. * In order to work, it has to be used in `app.component.ts`, as explained in the following snippet: * ``` export class AppComponent { constructor(private ngZone: NgZone, private auth0: IDEAAuth0Service) { App.addListener('appUrlOpen', ({ url }): void => this.ngZone.run((): void => this.auth0.handleCallbackOnMobileDevices(url)) ); } } * ``` */ async handleCallbackOnMobileDevices(url) { if (url?.startsWith(this._env.auth0.callbackUri)) { if (url.includes('state=') && (url.includes('error=') || url.includes('code='))) await firstValueFrom(this._auth0.handleRedirectCallback(url)); await Browser.close(); } } /** * Get the ID token, to use for authenticating API requests to the back-end. */ async getIdToken() { const { __raw } = await firstValueFrom(this._auth0.idTokenClaims$); return __raw; } /** * Whether the user is currently authenticated. */ async isUserAuthenticated() { return await firstValueFrom(this._auth0.isAuthenticated$); } /** * Get the current user and its data. */ async getUser() { const user = await firstValueFrom(this._auth0.user$); if (user) return new Auth0User(user); else return null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Service, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Service, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IDEAAuth0Service, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); const auth0Guard = async (_, state) => { const _auth = inject(IDEAAuth0Service); const _api = inject(IDEAApiService); if (!_api.authToken) _api.authToken = async () => { try { return getValidIdToken(_auth); } catch (error) { _auth.goToLogin(state.url); return null; } }; if (await _auth.isUserAuthenticated()) return true; else { _auth.goToLogin(state.url); return false; } }; /** * Get a valid ID token from the cache or, if expired, from the server. * Note: Auth0 consider the cache valid even if the ID Token expried (only checks for valid Access Tokens). */ const getValidIdToken = async (auth) => { const cacheRes = await firstValueFrom(auth.__raw.getAccessTokenSilently({ detailedResponse: true })); const { exp } = decodeJwt(cacheRes.id_token); const isTokenExpired = new Date(exp * 1000) < new Date(); if (!isTokenExpired) return cacheRes.id_token; else { const freshRes = await firstValueFrom(auth.__raw.getAccessTokenSilently({ detailedResponse: true, cacheMode: 'off' })); return freshRes.id_token; } }; /** * Decode a JWT without relying on external libraries. */ const decodeJwt = (token) => { const base64Url = token.split('.')[1]; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(window .atob(base64) .split('') .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)) .join('')); return JSON.parse(jsonPayload); }; /** * Generated bundle index. Do not edit. */ export { IDEAAuth0Module, IDEAAuth0Service, auth0Guard }; //# sourceMappingURL=idea-ionic-auth0.mjs.map