angular-simple-oidc
Version:
Angular Library implementing Open Id Connect specification. Code Flow, Refresh Tokens, Session Management, Discovery Document.
92 lines • 16.1 kB
JavaScript
import { Injectable, Inject } from '@angular/core';
import { OidcDiscoveryDocClient } from '../discovery-document/oidc-discovery-doc-client.service';
import { DynamicIframeService } from '../dynamic-iframe/dynamic-iframe.service';
import { take, map, tap, switchMap, takeUntil, filter, finalize, withLatestFrom } from 'rxjs/operators';
import { SessionCheckNotSupportedError, SessionCheckFailedError } from './errors';
import { TokenStorageService } from '../token-storage.service';
import { interval, fromEvent, Subject, combineLatest } from 'rxjs';
import { WINDOW_REF, AUTH_CONFIG_SERVICE } from '../providers';
import { SessionChangedEvent } from './events';
import { SESSION_MANAGEMENT_CONFIG_SERVICE } from './providers';
import { ConfigService } from 'angular-simple-oidc/config';
import { EventsService, SimpleOidcInfoEvent } from 'angular-simple-oidc/events';
// @dynamic
export class SessionCheckService {
constructor(window, discoveryClient, dynamicIframe, tokenStorage, config, sessionConfig, events) {
this.window = window;
this.discoveryClient = discoveryClient;
this.dynamicIframe = dynamicIframe;
this.tokenStorage = tokenStorage;
this.config = config;
this.sessionConfig = sessionConfig;
this.events = events;
this.destroyedSubject = new Subject();
}
ngOnDestroy() {
this.destroyedSubject.next();
this.destroyedSubject.complete();
}
startSessionCheck() {
const localState$ = this.tokenStorage.currentState$
.pipe(take(1));
const doc$ = this.discoveryClient.current$
.pipe(take(1));
const iframe = this.dynamicIframe
.create()
.hide();
return combineLatest(doc$, localState$)
.pipe(tap(() => this.events.dispatch(new SimpleOidcInfoEvent('Starting Session Check'))), map(([doc, localState]) => {
if (!doc.check_session_iframe || !localState.sessionState) {
throw new SessionCheckNotSupportedError({ doc, localState });
}
else {
iframe.setSource(doc.check_session_iframe)
.appendToBody();
return localState;
}
}), withLatestFrom(this.config.current$, this.sessionConfig.current$), take(1), switchMap(([localState, authConfig, sessionConfig]) => {
const expectedIframeOrigin = new URL(authConfig.openIDProviderUrl).origin;
const pollIframe$ = interval(sessionConfig.opIframePollInterval)
.pipe(map(() => `${authConfig.clientId.toLowerCase()} ${localState.sessionState}`), tap(msg => iframe.postMessage(msg, expectedIframeOrigin)));
const listen$ = fromEvent(this.window, 'message')
.pipe(filter((e) => e.origin === expectedIframeOrigin), map((e) => this.fireEventsFromMessage(e)), filter(msg => !!msg) // only the messages we care
);
return combineLatest(pollIframe$, listen$)
.pipe(map((arr) => arr[1]));
}), finalize(() => iframe.remove()), takeUntil(this.destroyedSubject.asObservable()));
}
/**
* The received data will either be changed or unchanged
* unless the syntax of the message sent was determined by the OP to be malformed,
* in which case the received data will be error.
* @param msg
*/
fireEventsFromMessage(msg) {
const result = msg.data;
switch (result) {
case 'changed':
this.events.dispatch(new SessionChangedEvent());
return result;
case 'unchanged':
return result;
case 'error':
throw new SessionCheckFailedError(msg);
default:
// If the message is not the one we expect, ignore it.
return null;
}
}
}
SessionCheckService.decorators = [
{ type: Injectable }
];
SessionCheckService.ctorParameters = () => [
{ type: Window, decorators: [{ type: Inject, args: [WINDOW_REF,] }] },
{ type: OidcDiscoveryDocClient },
{ type: DynamicIframeService },
{ type: TokenStorageService },
{ type: ConfigService, decorators: [{ type: Inject, args: [AUTH_CONFIG_SERVICE,] }] },
{ type: ConfigService, decorators: [{ type: Inject, args: [SESSION_MANAGEMENT_CONFIG_SERVICE,] }] },
{ type: EventsService }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbi1jaGVjay5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1zaW1wbGUtb2lkYy9zcmMvbGliL3Nlc3Npb24tbWFuYWdlbWVudC9zZXNzaW9uLWNoZWNrLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seURBQXlELENBQUM7QUFDakcsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDaEYsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RyxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDbEYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFL0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRSxPQUFPLEVBQUUsVUFBVSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUcvQyxPQUFPLEVBQUUsaUNBQWlDLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDaEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTNELE9BQU8sRUFBRSxhQUFhLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVoRixXQUFXO0FBRVgsTUFBTSxPQUFPLG1CQUFtQjtJQUk1QixZQUV1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QUFhLHVCQWtCYixNQUFNLFNBQUMsaUNBQWlDO1lBaEJ4QyxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBJbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9pZGNEaXNjb3ZlcnlEb2NDbGllbnQgfSBmcm9tICcuLi9kaXNjb3ZlcnktZG9jdW1lbnQvb2lkYy1kaXNjb3ZlcnktZG9jLWNsaWVudC5zZXJ2aWNlJztcbmltcG9ydCB7IER5bmFtaWNJZnJhbWVTZXJ2aWNlIH0gZnJvbSAnLi4vZHluYW1pYy1pZnJhbWUvZHluYW1pYy1pZnJhbWUuc2VydmljZSc7XG5pbXBvcnQgeyB0YWtlLCBtYXAsIHRhcCwgc3dpdGNoTWFwLCB0YWtlVW50aWwsIGZpbHRlciwgZmluYWxpemUsIHdpdGhMYXRlc3RGcm9tIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgU2Vzc2lvbkNoZWNrTm90U3VwcG9ydGVkRXJyb3IsIFNlc3Npb25DaGVja0ZhaWxlZEVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgVG9rZW5TdG9yYWdlU2VydmljZSB9IGZyb20gJy4uL3Rva2VuLXN0b3JhZ2Uuc2VydmljZSc7XG5pbXBvcnQgeyBEeW5hbWljSWZyYW1lIH0gZnJvbSAnLi4vZHluYW1pYy1pZnJhbWUvZHluYW1pYy1pZnJhbWUnO1xuaW1wb3J0IHsgaW50ZXJ2YWwsIGZyb21FdmVudCwgU3ViamVjdCwgY29tYmluZUxhdGVzdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgV0lORE9XX1JFRiwgQVVUSF9DT05GSUdfU0VSVklDRSB9IGZyb20gJy4uL3Byb3ZpZGVycyc7XG5pbXBvcnQgeyBTZXNzaW9uQ2hhbmdlZEV2ZW50IH0gZnJvbSAnLi9ldmVudHMnO1xuaW1wb3J0IHsgTG9jYWxTdGF0ZSB9IGZyb20gJ2FuZ3VsYXItc2ltcGxlLW9pZGMvY29yZSc7XG5pbXBvcnQgeyBTZXNzaW9uTWFuYWdlbWVudENvbmZpZyB9IGZyb20gJy4vbW9kZWxzJztcbmltcG9ydCB7IFNFU1NJT05fTUFOQUdFTUVOVF9DT05GSUdfU0VSVklDRSB9IGZyb20gJy4vcHJvdmlkZXJzJztcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICdhbmd1bGFyLXNpbXBsZS1vaWRjL2NvbmZpZyc7XG5pbXBvcnQgeyBBdXRoQ29uZmlnIH0gZnJvbSAnLi4vY29uZmlnL21vZGVscyc7XG5pbXBvcnQgeyBFdmVudHNTZXJ2aWNlLCBTaW1wbGVPaWRjSW5mb0V2ZW50IH0gZnJvbSAnYW5ndWxhci1zaW1wbGUtb2lkYy9ldmVudHMnO1xuXG4vLyBAZHluYW1pY1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNlc3Npb25DaGVja1NlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJvdGVjdGVkIGRlc3Ryb3llZFN1YmplY3QgPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIEBJbmplY3QoV0lORE9XX1JFRilcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHdpbmRvdzogV2luZG93LFxuICAgICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGlzY292ZXJ5Q2xpZW50OiBPaWRjRGlzY292ZXJ5RG9jQ2xpZW50LFxuICAgICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZHluYW1pY0lmcmFtZTogRHluYW1pY0lmcmFtZVNlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCByZWFkb25seSB0b2tlblN0b3JhZ2U6IFRva2VuU3RvcmFnZVNlcnZpY2UsXG4gICAgICAgIEBJbmplY3QoQVVUSF9DT05GSUdfU0VSVklDRSlcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbmZpZzogQ29uZmlnU2VydmljZTxBdXRoQ29uZmlnPixcbiAgICAgICAgQEluamVjdChTRVNTSU9OX01BTkFHRU1FTlRfQ09ORklHX1NFUlZJQ0UpXG4gICAgICAgIHByb3RlY3RlZCByZWFkb25seSBzZXNzaW9uQ29uZmlnOiBDb25maWdTZXJ2aWNlPFNlc3Npb25NYW5hZ2VtZW50Q29uZmlnPixcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGV2ZW50czogRXZlbnRzU2VydmljZSxcbiAgICApIHsgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3llZFN1YmplY3QubmV4dCgpO1xuICAgICAgICB0aGlzLmRlc3Ryb3llZFN1YmplY3QuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhcnRTZXNzaW9uQ2hlY2soKSB7XG4gICAgICAgIGNvbnN0IGxvY2FsU3RhdGUkID0gdGhpcy50b2tlblN0b3JhZ2UuY3VycmVudFN0YXRlJFxuICAgICAgICAgICAgLnBpcGUodGFrZSgxKSk7XG5cbiAgICAgICAgY29uc3QgZG9jJCA9IHRoaXMuZGlzY292ZXJ5Q2xpZW50LmN1cnJlbnQkXG4gICAgICAgICAgICAucGlwZSh0YWtlKDEpKTtcblxuICAgICAgICBjb25zdCBpZnJhbWUgPSB0aGlzLmR5bmFtaWNJZnJhbWVcbiAgICAgICAgICAgIC5jcmVhdGUoKVxuICAgICAgICAgICAgLmhpZGUoKTtcblxuICAgICAgICByZXR1cm4gY29tYmluZUxhdGVzdChkb2MkLCBsb2NhbFN0YXRlJClcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIHRhcCgoKSA9PiB0aGlzLmV2ZW50cy5kaXNwYXRjaChuZXcgU2ltcGxlT2lkY0luZm9FdmVudCgnU3RhcnRpbmcgU2Vzc2lvbiBDaGVjaycpKSksXG4gICAgICAgICAgICAgICAgbWFwKChbZG9jLCBsb2NhbFN0YXRlXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvYy5jaGVja19zZXNzaW9uX2lmcmFtZSB8fCAhbG9jYWxTdGF0ZS5zZXNzaW9uU3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBTZXNzaW9uQ2hlY2tOb3RTdXBwb3J0ZWRFcnJvcih7IGRvYywgbG9jYWxTdGF0ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmcmFtZS5zZXRTb3VyY2UoZG9jLmNoZWNrX3Nlc3Npb25faWZyYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmRUb0JvZHkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBsb2NhbFN0YXRlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgd2l0aExhdGVzdEZyb20odGhpcy5jb25maWcuY3VycmVudCQsIHRoaXMuc2Vzc2lvbkNvbmZpZy5jdXJyZW50JCksXG4gICAgICAgICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKFtsb2NhbFN0YXRlLCBhdXRoQ29uZmlnLCBzZXNzaW9uQ29uZmlnXSkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkSWZyYW1lT3JpZ2luID0gbmV3IFVSTChhdXRoQ29uZmlnLm9wZW5JRFByb3ZpZGVyVXJsKS5vcmlnaW47XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9sbElmcmFtZSQgPSBpbnRlcnZhbChzZXNzaW9uQ29uZmlnLm9wSWZyYW1lUG9sbEludGVydmFsKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKCgpID0+IGAke2F1dGhDb25maWcuY2xpZW50SWQudG9Mb3dlckNhc2UoKX0gJHtsb2NhbFN0YXRlLnNlc3Npb25TdGF0ZX1gKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAobXNnID0+IGlmcmFtZS5wb3N0TWVzc2FnZShtc2csIGV4cGVjdGVkSWZyYW1lT3JpZ2luKSksXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbiQgPSBmcm9tRXZlbnQodGhpcy53aW5kb3csICdtZXNzYWdlJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcigoZTogTWVzc2FnZUV2ZW50KSA9PiBlLm9yaWdpbiA9PT0gZXhwZWN0ZWRJZnJhbWVPcmlnaW4pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgoZTogTWVzc2FnZUV2ZW50KSA9PiB0aGlzLmZpcmVFdmVudHNGcm9tTWVzc2FnZShlKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKG1zZyA9PiAhIW1zZykgIC8vIG9ubHkgdGhlIG1lc3NhZ2VzIHdlIGNhcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QocG9sbElmcmFtZSQsIGxpc3RlbiQpXG4gICAgICAgICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGFycikgPT4gYXJyWzFdKSwgLy8ganVzdCBrZWVwIHRoZSBtZXNzYWdlIHJlc3BvbnNlIGFuZCBkcm9wIHRoZSBpbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiBpZnJhbWUucmVtb3ZlKCkpLFxuICAgICAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3llZFN1YmplY3QuYXNPYnNlcnZhYmxlKCkpLFxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjZWl2ZWQgZGF0YSB3aWxsIGVpdGhlciBiZSBjaGFuZ2VkIG9yIHVuY2hhbmdlZFxuICAgICAqIHVubGVzcyB0aGUgc3ludGF4IG9mIHRoZSBtZXNzYWdlIHNlbnQgd2FzIGRldGVybWluZWQgYnkgdGhlIE9QIHRvIGJlIG1hbGZvcm1lZCxcbiAgICAgKiBpbiB3aGljaCBjYXNlIHRoZSByZWNlaXZlZCBkYXRhIHdpbGwgYmUgZXJyb3IuXG4gICAgICogQHBhcmFtIG1zZ1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaXJlRXZlbnRzRnJvbU1lc3NhZ2UobXNnOiBNZXNzYWdlRXZlbnQpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gbXNnLmRhdGEgYXMgc3RyaW5nO1xuICAgICAgICBzd2l0Y2ggKHJlc3VsdCkge1xuICAgICAgICAgICAgY2FzZSAnY2hhbmdlZCc6XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudHMuZGlzcGF0Y2gobmV3IFNlc3Npb25DaGFuZ2VkRXZlbnQoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ3VuY2hhbmdlZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIGNhc2UgJ2Vycm9yJzpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU2Vzc2lvbkNoZWNrRmFpbGVkRXJyb3IobXNnKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG1lc3NhZ2UgaXMgbm90IHRoZSBvbmUgd2UgZXhwZWN0LCBpZ25vcmUgaXQuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=