@kephas/ngx-oidc
Version:
Provides the integration of the OIDC API with Kephas and Angular 12+.
111 lines • 16.6 kB
JavaScript
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=