@idea-ionic/auth0
Version:
183 lines (177 loc) • 7.42 kB
JavaScript
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