UNPKG

@asgardeo/auth-angular

Version:
638 lines (623 loc) 22.6 kB
import * as i0 from '@angular/core'; import { InjectionToken, Injectable, Injector, Inject, Component, NgModule } from '@angular/core'; import { AsgardeoSPAClient, Hooks, SPAUtils } from '@asgardeo/auth-spa'; export { Hooks, ResponseMode, Storage } from '@asgardeo/auth-spa'; import { __awaiter } from 'tslib'; import { BehaviorSubject, Subject, from } from 'rxjs'; import { Router } from '@angular/router'; import { takeUntil, mergeMap, catchError } from 'rxjs/operators'; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ const ASGARDEO_CONFIG = new InjectionToken("Asgardeo.config.angular"); /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class AsgardeoNavigatorService { constructor(injector) { try { this.router = injector.get(Router); } catch (_a) { console.warn("Router is Not Provided"); } } navigateByUrl(url) { if (this.router) { return this.router.navigateByUrl(url); } else { return Promise.resolve(false); } } setRedirectUrl() { sessionStorage.setItem("redirectUrl", this.getCurrentRoute()); } getRedirectUrl() { return sessionStorage.getItem("redirectUrl") || "/"; } getRouteWithoutParams(url) { return new URL(url).pathname; } getCurrentRoute() { if (this.router) { return this.router.url.split("?")[0]; } else { return window.location.href.split("?")[0]; } } getCurrentUrl() { if (this.router) { return this.router.url; } else { return window.location.href; } } } AsgardeoNavigatorService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoNavigatorService_Factory() { return new AsgardeoNavigatorService(i0.ɵɵinject(i0.INJECTOR)); }, token: AsgardeoNavigatorService, providedIn: "root" }); AsgardeoNavigatorService.decorators = [ { type: Injectable, args: [{ providedIn: "root" },] } ]; AsgardeoNavigatorService.ctorParameters = () => [ { type: Injector } ]; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class AsgardeoAuthStateStoreService { constructor() { this.DEFAULT_STATE = { allowedScopes: "", displayName: "", email: "", isAuthenticated: false, isLoading: true, sub: "", username: "" }; // Readonly State BehaviorSubject. Not accessible from outside. this._state = new BehaviorSubject(this.DEFAULT_STATE); // Outside can access this readonly state object by subscribing. this.state$ = this._state.asObservable(); } /** * Getter for the state. * @return {AuthStateInterface} */ get state() { return this._state.getValue(); } /** * Setter for the state. * @param {AuthStateInterface} newState - New state. */ set state(newState) { this._state.next(Object.assign(Object.assign({}, this._state), newState)); } /** * Set the Loading state. * @param {boolean} isLoading - State. */ setIsLoading(isLoading) { this._state.next(Object.assign(Object.assign({}, this.state), { isLoading })); } /** * Resets the state back to the default. */ reset() { this._state.next(this.DEFAULT_STATE); } } AsgardeoAuthStateStoreService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthStateStoreService_Factory() { return new AsgardeoAuthStateStoreService(); }, token: AsgardeoAuthStateStoreService, providedIn: "root" }); AsgardeoAuthStateStoreService.decorators = [ { type: Injectable, args: [{ providedIn: "root" },] } ]; class AsgardeoAuthService { constructor(authConfig, navigator, stateStore) { this.authConfig = authConfig; this.navigator = navigator; this.stateStore = stateStore; this.state$ = this.stateStore.state$; this.auth = AsgardeoSPAClient.getInstance(); this.subscriptionDestroyer$ = new Subject(); /** * This method allows you to sign in silently. * First, this method sends a prompt none request to see if there is an active user session in the identity server. * If there is one, then it requests the access token and stores it. Else, it returns false. * * @return {Promise<BasicUserInfo | boolean>} - A Promise that resolves with the user information after signing in * or with `false` if the user is not signed in. * * @example *``` * this.auth.trySignInSilently() *``` */ this.trySignInSilently = () => __awaiter(this, void 0, void 0, function* () { this.stateStore.setIsLoading(true); return this.auth .trySignInSilently() .then((response) => __awaiter(this, void 0, void 0, function* () { if (!response) { return false; } if (yield this.auth.isAuthenticated()) { const basicUserInfo = response; this.stateStore.state = { allowedScopes: basicUserInfo.allowedScopes, displayName: basicUserInfo.displayName, email: basicUserInfo.email, isAuthenticated: true, isLoading: false, sub: basicUserInfo.sub, username: basicUserInfo.username }; } return response; })) .catch((error) => Promise.reject(error)) .finally(() => { this.stateStore.setIsLoading(false); }); }); this.config = authConfig; this.auth = AsgardeoSPAClient.getInstance(); this.initializeHooks(); (() => __awaiter(this, void 0, void 0, function* () { yield this.auth.initialize(this.authConfig); yield this.handleSingleLogoutOnRedirect(); this.handleAutoLogin() .pipe(takeUntil(this.subscriptionDestroyer$)) .subscribe(); }))(); } /** * Runs on service unmount. * @remarks Housekeeping logic such as un-subscribing should go here. */ ngOnDestroy() { this.subscriptionDestroyer$.next(true); this.subscriptionDestroyer$.unsubscribe(); } /** * Registering a sign-out hook clears user session data internally if there was a successful logout. */ initializeHooks() { this.auth.on(Hooks.SignOut, () => { }); } signIn(config, authorizationCode, sessionState) { this.stateStore.setIsLoading(true); return this.auth .signIn(config, authorizationCode, sessionState) .then((response) => __awaiter(this, void 0, void 0, function* () { if (!response) { return; } if (yield this.auth.isAuthenticated()) { this.stateStore.state = { allowedScopes: response.allowedScopes, displayName: response.displayName, email: response.email, isAuthenticated: true, isLoading: false, sub: response.sub, username: response.username }; } return response; })) .catch((error) => Promise.reject(error)) .finally(() => { this.stateStore.setIsLoading(false); }); } signInWithRedirect() { this.navigator.setRedirectUrl(); const redirectRoute = this.navigator.getRouteWithoutParams(this.authConfig.signInRedirectURL); return this.navigator.navigateByUrl(redirectRoute); } signOut() { this.stateStore.setIsLoading(true); return this.auth .signOut() .then((response) => { // Reset the state. this.stateStore.reset(); return response; }) .catch((error) => Promise.reject(error)) .finally(() => { this.stateStore.setIsLoading(false); }); } isAuthenticated() { return this.auth.isAuthenticated(); } getBasicUserInfo() { return this.auth.getBasicUserInfo(); } getAccessToken() { return this.auth.getAccessToken(); } getIDToken() { return this.auth.getIDToken(); } getDecodedIDToken() { return this.auth.getDecodedIDToken(); } getOIDCServiceEndpoints() { return this.auth.getOIDCServiceEndpoints(); } refreshAccessToken() { return this.auth.refreshAccessToken(); } revokeAccessToken() { return this.auth .revokeAccessToken() .then(() => { // Reset the state. this.stateStore.reset(); return true; }) .catch((error) => Promise.reject(error)) .finally(() => { this.stateStore.setIsLoading(false); }); } on(hook, callback, id) { if (hook === Hooks.CustomGrant) { return this.auth.on(hook, callback, id); } return this.auth.on(hook, callback); } requestCustomGrant(config) { return this.auth.requestCustomGrant(config); } httpRequest(config) { return this.auth.httpRequest(config); } httpRequestAll(config) { return this.auth.httpRequestAll(config); } /** * Handles auto login by trying to exchange tokens if auth params i.e `code` and `session_state` is * available in the URL or else, tries to silently login. * * @private * @return {Observable<BasicUserInfo | boolean>} */ handleAutoLogin() { this.stateStore.setIsLoading(true); // If `skipRedirectCallback` is not true, check if the URL has `code` and `session_state` params. // If so, initiate the sign in. If not, try to login silently. if (!this.config.skipRedirectCallback && SPAUtils.hasAuthSearchParamsInURL()) { return from(this.signIn()); } // This uses the RP iframe to get the session. Hence, will not work if 3rd party cookies are disabled. // If the browser has these cookies disabled, we'll not be able to retrieve the session on refreshes. return from(this.trySignInSilently()); } /** * Handles single logout if a prompt none sign in response is received with an error parameter on the URL. * * @private * @return {Promise<BasicUserInfo | void>} */ handleSingleLogoutOnRedirect() { return __awaiter(this, void 0, void 0, function* () { if (SPAUtils.hasErrorInURL()) { // The signIn method call will call receivePromptNoneResponse method internally to handle the prompt none // response in the single logout flow. return this.signIn({ callOnlyOnRedirect: true }); } }); } } AsgardeoAuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthService_Factory() { return new AsgardeoAuthService(i0.ɵɵinject(ASGARDEO_CONFIG), i0.ɵɵinject(AsgardeoNavigatorService), i0.ɵɵinject(AsgardeoAuthStateStoreService)); }, token: AsgardeoAuthService, providedIn: "root" }); AsgardeoAuthService.decorators = [ { type: Injectable, args: [{ providedIn: "root" },] } ]; AsgardeoAuthService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [ASGARDEO_CONFIG,] }] }, { type: AsgardeoNavigatorService }, { type: AsgardeoAuthStateStoreService } ]; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class AsgardeoSignInRedirectComponent { constructor(auth, navigator) { this.auth = auth; this.navigator = navigator; } ngOnInit() { this.auth.on(Hooks.SignIn, () => { this.navigator.navigateByUrl(this.navigator.getRedirectUrl()); }); if (!SPAUtils.hasAuthSearchParamsInURL(this.navigator.getCurrentUrl())) { this.auth.signIn(); } } } AsgardeoSignInRedirectComponent.decorators = [ { type: Component, args: [{ selector: "lib-asgardeo-sign-in-redirect", template: "" },] } ]; AsgardeoSignInRedirectComponent.ctorParameters = () => [ { type: AsgardeoAuthService }, { type: AsgardeoNavigatorService } ]; class AsgardeoAuthGuard { constructor(auth) { this.auth = auth; } canActivate() { return __awaiter(this, void 0, void 0, function* () { const isAuthenticated = yield this.auth.isAuthenticated(); if (isAuthenticated) { return true; } return false; }); } canActivateChild() { return __awaiter(this, void 0, void 0, function* () { return this.canActivate(); }); } } AsgardeoAuthGuard.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthGuard_Factory() { return new AsgardeoAuthGuard(i0.ɵɵinject(AsgardeoAuthService)); }, token: AsgardeoAuthGuard, providedIn: "root" }); AsgardeoAuthGuard.decorators = [ { type: Injectable, args: [{ providedIn: "root" },] } ]; AsgardeoAuthGuard.ctorParameters = () => [ { type: AsgardeoAuthService } ]; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class AsgardeoAuthModule { static forRoot(config) { return { ngModule: AsgardeoAuthModule, providers: [ AsgardeoAuthService, AsgardeoAuthGuard, { provide: ASGARDEO_CONFIG, useValue: config } ] }; } } AsgardeoAuthModule.decorators = [ { type: NgModule, args: [{ declarations: [AsgardeoSignInRedirectComponent] },] } ]; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class AsgardeoAuthInterceptor { constructor(auth, authConfig) { this.auth = auth; this.authConfig = authConfig; } intercept(request, next) { if (this.canAttachToken(request, this.authConfig["resourceServerURLs"])) { return from(this.auth.getAccessToken()) .pipe(mergeMap(token => { if (token) { const header = "Bearer " + token; const headers = request.headers.set("Authorization", header); request = request.clone({ headers }); } return next.handle(request); }), catchError(error => { console.error(error); return next.handle(request); })); } else { return next.handle(request); } } canAttachToken(request, allowedUrls) { let matches = false; if (allowedUrls) { allowedUrls.forEach((baseUrl) => { var _a; if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.startsWith(baseUrl)) { matches = true; } }); } return matches; } } AsgardeoAuthInterceptor.decorators = [ { type: Injectable } ]; AsgardeoAuthInterceptor.ctorParameters = () => [ { type: AsgardeoAuthService }, { type: undefined, decorators: [{ type: Inject, args: [ASGARDEO_CONFIG,] }] } ]; /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * Generated bundle index. Do not edit. */ export { AsgardeoAuthGuard, AsgardeoAuthInterceptor, AsgardeoAuthModule, AsgardeoAuthService, AsgardeoSignInRedirectComponent, ASGARDEO_CONFIG as ɵa, AsgardeoNavigatorService as ɵc, AsgardeoAuthStateStoreService as ɵd, AsgardeoAuthService as ɵe }; //# sourceMappingURL=asgardeo-auth-angular.js.map