UNPKG

angular-simple-oidc

Version:

Angular Library implementing Open Id Connect specification. Code Flow, Refresh Tokens, Session Management, Discovery Document.

92 lines 16.1 kB
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=