UNPKG

@kephas/ngx-oidc

Version:

Provides the integration of the OIDC API with Kephas and Angular 12+.

111 lines 16.6 kB
import { Component } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { take } from 'rxjs/operators'; import { AuthenticationResultStatus, AuthenticationService } from '../authentication.service'; import { AuthenticationSettingsProvider, LogoutActions } from '../authentication.settings'; import * as i0 from "@angular/core"; import * as i1 from "../authentication.service"; import * as i2 from "@angular/router"; import * as i3 from "../authentication.settings"; import * as i4 from "@angular/common"; // The main responsibility of this component is to handle the user's logout process. // This is the starting point for the logout process, which is usually initiated when a // user clicks on the logout button on the LoginMenu component. export class LogoutComponent { constructor(authenticationService, activatedRoute, router, authSettingsProvider) { this.authenticationService = authenticationService; this.activatedRoute = activatedRoute; this.router = router; this.authSettingsProvider = authSettingsProvider; this.message = new BehaviorSubject(null); } async ngOnInit() { const action = this.activatedRoute.snapshot.url[1]; switch (action.path) { case LogoutActions.Logout: if (!!window.history.state.local) { await this.logout(this.getReturnUrl()); } else { // This prevents regular links to <app>/authentication/logout from triggering a logout this.message.next('The logout was not initiated from within the page.'); } break; case LogoutActions.LogoutCallback: await this.processLogoutCallback(); break; case LogoutActions.LoggedOut: this.message.next('You successfully logged out!'); break; default: throw new Error(`Invalid action '${action}'`); } } async logout(returnUrl) { const state = { returnUrl }; const isauthenticated = await this.authenticationService.isAuthenticated().pipe(take(1)).toPromise(); if (isauthenticated) { const result = await this.authenticationService.signOut(state); switch (result.status) { case AuthenticationResultStatus.Redirect: break; case AuthenticationResultStatus.Success: await this.navigateToReturnUrl(returnUrl); break; case AuthenticationResultStatus.Fail: this.message.next(result.message); break; default: throw new Error('Invalid authentication result status.'); } } else { this.message.next('You successfully logged out!'); } } async processLogoutCallback() { const url = window.location.href; const result = await this.authenticationService.completeSignOut(url); switch (result.status) { case AuthenticationResultStatus.Redirect: // There should not be any redirects as the only time completeAuthentication finishes // is when we are doing a redirect sign in flow. throw new Error('Should not redirect.'); case AuthenticationResultStatus.Success: await this.navigateToReturnUrl(this.getReturnUrl(result.state)); break; case AuthenticationResultStatus.Fail: this.message.next(result.message); break; default: throw new Error('Invalid authentication result status.'); } } async navigateToReturnUrl(returnUrl) { await this.router.navigateByUrl(returnUrl, { replaceUrl: true }); } getReturnUrl(state) { const fromQuery = this.activatedRoute.snapshot.queryParams.returnUrl; // If the url is comming from the query string, check that is either // a relative url or an absolute url if (fromQuery && !(fromQuery.startsWith(`${window.location.origin}/`) || /\/[^\/].*/.test(fromQuery))) { // This is an extra check to prevent open redirects. throw new Error('Invalid return url. The return url needs to have the same origin as the current page.'); } return (state && state.returnUrl) || fromQuery || this.authSettingsProvider.settings.applicationPaths.LoggedOut; } } LogoutComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LogoutComponent, deps: [{ token: i1.AuthenticationService }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i3.AuthenticationSettingsProvider }], target: i0.ɵɵFactoryTarget.Component }); LogoutComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LogoutComponent, selector: "app-logout", ngImport: i0, template: "<p>{{ message | async }}</p>", styles: [""], pipes: { "async": i4.AsyncPipe } }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LogoutComponent, decorators: [{ type: Component, args: [{ selector: 'app-logout', template: "<p>{{ message | async }}</p>", styles: [""] }] }], ctorParameters: function () { return [{ type: i1.AuthenticationService }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i3.AuthenticationSettingsProvider }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nb3V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2tlcGhhcy9uZ3gtb2lkYy9zcmMvbGliL2xvZ291dC9sb2dvdXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva2VwaGFzL25neC1vaWRjL3NyYy9saWIvbG9nb3V0L2xvZ291dC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdkMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxFQUFFLDBCQUEwQixFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDOUYsT0FBTyxFQUFFLDhCQUE4QixFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDOzs7Ozs7QUFHM0Ysb0ZBQW9GO0FBQ3BGLHVGQUF1RjtBQUN2RiwrREFBK0Q7QUFNL0QsTUFBTSxPQUFPLGVBQWU7SUFHMUIsWUFDVSxxQkFBNEMsRUFDNUMsY0FBOEIsRUFDOUIsTUFBYyxFQUNkLG9CQUFvRDtRQUhwRCwwQkFBcUIsR0FBckIscUJBQXFCLENBQXVCO1FBQzVDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFnQztRQU52RCxZQUFPLEdBQUcsSUFBSSxlQUFlLENBQXdCLElBQUksQ0FBQyxDQUFDO0lBTUEsQ0FBQztJQUVuRSxLQUFLLENBQUMsUUFBUTtRQUNaLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFB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QUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxTQUFpQjtRQUNqRCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRTtZQUN6QyxVQUFVLEVBQUUsSUFBSTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sWUFBWSxDQUFDLEtBQXVCO1FBQzFDLE1BQU0sU0FBUyxHQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFdBQStCLENBQUMsU0FBUyxDQUFDO1FBQzFGLG9FQUFvRTtRQUNwRSxvQ0FBb0M7UUFDcEMsSUFBSSxTQUFTO1lBQ1gsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDO2dCQUNsRCxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUU7WUFDaEMsb0RBQW9EO1lBQ3BELE1BQU0sSUFBSSxLQUFLLENBQUMsdUZBQXVGLENBQUMsQ0FBQztTQUMxRztRQUNELE9BQU8sQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLFNBQVMsQ0FBQztZQUMvQixTQUFTO1lBQ1QsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUM7SUFDbEUsQ0FBQzs7NEdBOUZVLGVBQWU7Z0dBQWYsZUFBZSxrRENoQjVCLDhCQUE0QjsyRkRnQmYsZUFBZTtrQkFMM0IsU0FBUzsrQkFDRSxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQgeyB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBBdXRoZW50aWNhdGlvblJlc3VsdFN0YXR1cywgQXV0aGVudGljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vYXV0aGVudGljYXRpb24uc2VydmljZSc7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uU2V0dGluZ3NQcm92aWRlciwgTG9nb3V0QWN0aW9ucyB9IGZyb20gJy4uL2F1dGhlbnRpY2F0aW9uLnNldHRpbmdzJztcclxuaW1wb3J0IHsgTmF2aWdhdGlvblN0YXRlIH0gZnJvbSAnLi4vbmF2aWdhdGlvblN0YXRlJztcclxuXHJcbi8vIFRoZSBtYWluIHJlc3BvbnNpYmlsaXR5IG9mIHRoaXMgY29tcG9uZW50IGlzIHRvIGhhbmRsZSB0aGUgdXNlcidzIGxvZ291dCBwcm9jZXNzLlxyXG4vLyBUaGlzIGlzIHRoZSBzdGFydGluZyBwb2ludCBmb3IgdGhlIGxvZ291dCBwcm9jZXNzLCB3aGljaCBpcyB1c3VhbGx5IGluaXRpYXRlZCB3aGVuIGFcclxuLy8gdXNlciBjbGlja3Mgb24gdGhlIGxvZ291dCBidXR0b24gb24gdGhlIExvZ2luTWVudSBjb21wb25lbnQuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYXBwLWxvZ291dCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2xvZ291dC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vbG9nb3V0LmNvbXBvbmVudC5jc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgTG9nb3V0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBwdWJsaWMgbWVzc2FnZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgRXJyb3IgfCBudWxsPihudWxsKTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGF1dGhlbnRpY2F0aW9uU2VydmljZTogQXV0aGVudGljYXRpb25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUsXHJcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxyXG4gICAgcHJpdmF0ZSBhdXRoU2V0dGluZ3NQcm92aWRlcjogQXV0aGVudGljYXRpb25TZXR0aW5nc1Byb3ZpZGVyKSB7IH1cclxuXHJcbiAgYXN5bmMgbmdPbkluaXQoKSB7XHJcbiAgICBjb25zdCBhY3Rpb24gPSB0aGlzLmFjdGl2YXRlZFJvdXRlLnNuYXBzaG90LnVybFsxXTtcclxuICAgIHN3aXRjaCAoYWN0aW9uLnBhdGgpIHtcclxuICAgICAgY2FzZSBMb2dvdXRBY3Rpb25zLkxvZ291dDpcclxuICAgICAgICBpZiAoISF3aW5kb3cuaGlzdG9yeS5zdGF0ZS5sb2NhbCkge1xyXG4gICAgICAgICAgYXdhaXQgdGhpcy5sb2dvdXQodGhpcy5nZXRSZXR1cm5VcmwoKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgcmVndWxhciBsaW5rcyB0byA8YXBwPi9hdXRoZW50aWNhdGlvbi9sb2dvdXQgZnJvbSB0cmlnZ2VyaW5nIGEgbG9nb3V0XHJcbiAgICAgICAgICB0aGlzLm1lc3NhZ2UubmV4dCgnVGhlIGxvZ291dCB3YXMgbm90IGluaXRpYXRlZCBmcm9tIHdpdGhpbiB0aGUgcGFnZS4nKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIExvZ291dEFjdGlvbnMuTG9nb3V0Q2FsbGJhY2s6XHJcbiAgICAgICAgYXdhaXQgdGhpcy5wcm9jZXNzTG9nb3V0Q2FsbGJhY2soKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBMb2dvdXRBY3Rpb25zLkxvZ2dlZE91dDpcclxuICAgICAgICB0aGlzLm1lc3NhZ2UubmV4dCgnWW91IHN1Y2Nlc3NmdWxseSBsb2dnZWQgb3V0IScpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhY3Rpb24gJyR7YWN0aW9ufSdgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgbG9nb3V0KHJldHVyblVybDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBjb25zdCBzdGF0ZTogTmF2aWdhdGlvblN0YXRlID0geyByZXR1cm5VcmwgfTtcclxuICAgIGNvbnN0IGlzYXV0aGVudGljYXRlZCA9IGF3YWl0IHRoaXMuYXV0aGVudGljYXRpb25TZXJ2aWNlLmlzQXV0aGVudGljYXRlZCgpLnBpcGUoXHJcbiAgICAgIHRha2UoMSlcclxuICAgICkudG9Qcm9taXNlKCk7XHJcbiAgICBpZiAoaXNhdXRoZW50aWNhdGVkKSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYXV0aGVudGljYXRpb25TZXJ2aWNlLnNpZ25PdXQoc3RhdGUpO1xyXG4gICAgICBzd2l0Y2ggKHJlc3VsdC5zdGF0dXMpIHtcclxuICAgICAgICBjYXNlIEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLlJlZGlyZWN0OlxyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSBBdXRoZW50aWNhdGlvblJlc3VsdFN0YXR1cy5TdWNjZXNzOlxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5uYXZpZ2F0ZVRvUmV0dXJuVXJsKHJldHVyblVybCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLkZhaWw6XHJcbiAgICAgICAgICB0aGlzLm1lc3NhZ2UubmV4dChyZXN1bHQubWVzc2FnZSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGF1dGhlbnRpY2F0aW9uIHJlc3VsdCBzdGF0dXMuJyk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMubWVzc2FnZS5uZXh0KCdZb3Ugc3VjY2Vzc2Z1bGx5IGxvZ2dlZCBvdXQhJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIHByb2Nlc3NMb2dvdXRDYWxsYmFjaygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGNvbnN0IHVybCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xyXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5hdXRoZW50aWNhdGlvblNlcnZpY2UuY29tcGxldGVTaWduT3V0KHVybCk7XHJcbiAgICBzd2l0Y2ggKHJlc3VsdC5zdGF0dXMpIHtcclxuICAgICAgY2FzZSBBdXRoZW50aWNhdGlvblJlc3VsdFN0YXR1cy5SZWRpcmVjdDpcclxuICAgICAgICAvLyBUaGVyZSBzaG91bGQgbm90IGJlIGFueSByZWRpcmVjdHMgYXMgdGhlIG9ubHkgdGltZSBjb21wbGV0ZUF1dGhlbnRpY2F0aW9uIGZpbmlzaGVzXHJcbiAgICAgICAgLy8gaXMgd2hlbiB3ZSBhcmUgZG9pbmcgYSByZWRpcmVjdCBzaWduIGluIGZsb3cuXHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaG91bGQgbm90IHJlZGlyZWN0LicpO1xyXG4gICAgICBjYXNlIEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLlN1Y2Nlc3M6XHJcbiAgICAgICAgYXdhaXQgdGhpcy5uYXZpZ2F0ZVRvUmV0dXJuVXJsKHRoaXMuZ2V0UmV0dXJuVXJsKHJlc3VsdC5zdGF0ZSkpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLkZhaWw6XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlLm5leHQocmVzdWx0Lm1lc3NhZ2UpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhdXRoZW50aWNhdGlvbiByZXN1bHQgc3RhdHVzLicpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBuYXZpZ2F0ZVRvUmV0dXJuVXJsKHJldHVyblVybDogc3RyaW5nKSB7XHJcbiAgICBhd2FpdCB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKHJldHVyblVybCwge1xyXG4gICAgICByZXBsYWNlVXJsOiB0cnVlXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0UmV0dXJuVXJsKHN0YXRlPzogTmF2aWdhdGlvblN0YXRlKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGZyb21RdWVyeSA9ICh0aGlzLmFjdGl2YXRlZFJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zIGFzIE5hdmlnYXRpb25TdGF0ZSkucmV0dXJuVXJsO1xyXG4gICAgLy8gSWYgdGhlIHVybCBpcyBjb21taW5nIGZyb20gdGhlIHF1ZXJ5IHN0cmluZywgY2hlY2sgdGhhdCBpcyBlaXRoZXJcclxuICAgIC8vIGEgcmVsYXRpdmUgdXJsIG9yIGFuIGFic29sdXRlIHVybFxyXG4gICAgaWYgKGZyb21RdWVyeSAmJlxyXG4gICAgICAhKGZyb21RdWVyeS5zdGFydHNXaXRoKGAke3dpbmRvdy5sb2NhdGlvbi5vcmlnaW59L2ApIHx8XHJcbiAgICAgICAgL1xcL1teXFwvXS4qLy50ZXN0KGZyb21RdWVyeSkpKSB7XHJcbiAgICAgIC8vIFRoaXMgaXMgYW4gZXh0cmEgY2hlY2sgdG8gcHJldmVudCBvcGVuIHJlZGlyZWN0cy5cclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHJldHVybiB1cmwuIFRoZSByZXR1cm4gdXJsIG5lZWRzIHRvIGhhdmUgdGhlIHNhbWUgb3JpZ2luIGFzIHRoZSBjdXJyZW50IHBhZ2UuJyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gKHN0YXRlICYmIHN0YXRlLnJldHVyblVybCkgfHxcclxuICAgICAgZnJvbVF1ZXJ5IHx8XHJcbiAgICAgIHRoaXMuYXV0aFNldHRpbmdzUHJvdmlkZXIuc2V0dGluZ3MuYXBwbGljYXRpb25QYXRocy5Mb2dnZWRPdXQ7XHJcbiAgfVxyXG59XHJcbiIsIjxwPnt7IG1lc3NhZ2UgfCBhc3luYyB9fTwvcD4iXX0=