UNPKG

angular-simple-oidc

Version:

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

79 lines 13.4 kB
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { switchMap, take, map, tap } from 'rxjs/operators'; import { TokenValidationService, TokenHelperService, SimpleOidcError } from 'angular-simple-oidc/core'; import { OidcDiscoveryDocClient } from './discovery-document/oidc-discovery-doc-client.service'; import { TokenEndpointError, TokenEndpointUnexpectedError } from './errors'; import { TokensObtainedEvent } from './auth.events'; import { EventsService, SimpleOidcInfoEvent } from 'angular-simple-oidc/events'; export class TokenEndpointClientService { constructor(http, discoveryDocumentClient, tokenValidation, tokenHelper, events) { this.http = http; this.discoveryDocumentClient = discoveryDocumentClient; this.tokenValidation = tokenValidation; this.tokenHelper = tokenHelper; this.events = events; } call(payload) { const headers = new HttpHeaders() .set('Content-Type', 'application/x-www-form-urlencoded'); return this.discoveryDocumentClient.current$ .pipe(take(1), switchMap(({ token_endpoint }) => { this.events.dispatch(new SimpleOidcInfoEvent(`Executing Token Endpoint`, { url: token_endpoint, payload })); return this.http.post(token_endpoint, payload, { headers: headers }); }), tap({ error: (e) => { if (e instanceof SimpleOidcError) { return; } if (e.status === 400) { // https://tools.ietf.org/html/rfc6749#section-5.2 throw new TokenEndpointError(e.error.error, e); } else { throw new TokenEndpointUnexpectedError(e); } } }), map(response => { let expiresAt; if (response.expires_in) { expiresAt = this.tokenHelper.getExpirationFromExpiresIn(response.expires_in); } else { this.events.dispatch(new SimpleOidcInfoEvent(`Token Response did not contain expires_in`, response)); } let decodedToken; if (response.id_token) { this.events.dispatch(new SimpleOidcInfoEvent(`Validating Identity Token format`, response.id_token)); this.tokenValidation.validateIdTokenFormat(response.id_token); decodedToken = this.tokenHelper.getPayloadFromToken(response.id_token); this.events.dispatch(new SimpleOidcInfoEvent(`Identity Token Payload decoded`, decodedToken)); } else { this.events.dispatch(new SimpleOidcInfoEvent(`Token Response did not contain id_token`, response)); } const result = { accessToken: response.access_token, accessTokenExpiresIn: response.expires_in, accessTokenExpiresAt: expiresAt ? expiresAt.getTime() : null, error: response.error, idToken: response.id_token, refreshToken: response.refresh_token, decodedIdToken: decodedToken }; this.events.dispatch(new TokensObtainedEvent(result)); return result; })); } } TokenEndpointClientService.decorators = [ { type: Injectable } ]; TokenEndpointClientService.ctorParameters = () => [ { type: HttpClient }, { type: OidcDiscoveryDocClient }, { type: TokenValidationService }, { type: TokenHelperService }, { type: EventsService } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tZW5kcG9pbnQtY2xpZW50LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLXNpbXBsZS1vaWRjL3NyYy9saWIvdG9rZW4tZW5kcG9pbnQtY2xpZW50LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQWMsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkUsT0FBTyxFQUdILHNCQUFzQixFQUN0QixrQkFBa0IsRUFDbEIsZUFBZSxFQUNsQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHdEQUF3RCxDQUFDO0FBQ2hHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSw0QkFBNEIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUM1RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBV2hGLE1BQU0sT0FBTywwQkFBMEI7SUFFbkMsWUFDdUIsSUFBZ0IsRUFDaEIsdUJBQStDLEVBQy9DLGVBQXVDLEVBQ3ZDLFdBQStCLEVBQy9CLE1BQXFCO1FBSnJCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF3QjtRQUMvQyxvQkFBZSxHQUFmLGVBQWUsQ0FBd0I7UUFDdkMsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO1FBQy9CLFdBQU0sR0FBTixNQUFNLENBQWU7SUFDeEMsQ0FBQztJQUVFLElBQUksQ0FBQyxPQUFlO1FBQ3ZCLE1BQU0sT0FB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QkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBRXRELE9BQU8sTUFBTSxDQUFDO1FBQ2xCLENBQUMsQ0FBQyxDQUNMLENBQUM7SUFDVixDQUFDOzs7WUEzRUosVUFBVTs7O1lBdEJGLFVBQVU7WUFTVixzQkFBc0I7WUFKM0Isc0JBQXNCO1lBQ3RCLGtCQUFrQjtZQU1iLGFBQWEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwSGVhZGVycywgSHR0cEVycm9yUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHRha2UsIG1hcCwgY2F0Y2hFcnJvciwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgICBUb2tlblJlcXVlc3RSZXN1bHQsXG4gICAgRGVjb2RlZElkZW50aXR5VG9rZW4sXG4gICAgVG9rZW5WYWxpZGF0aW9uU2VydmljZSxcbiAgICBUb2tlbkhlbHBlclNlcnZpY2UsXG4gICAgU2ltcGxlT2lkY0Vycm9yXG59IGZyb20gJ2FuZ3VsYXItc2ltcGxlLW9pZGMvY29yZSc7XG5pbXBvcnQgeyBPaWRjRGlzY292ZXJ5RG9jQ2xpZW50IH0gZnJvbSAnLi9kaXNjb3ZlcnktZG9jdW1lbnQvb2lkYy1kaXNjb3ZlcnktZG9jLWNsaWVudC5zZXJ2aWNlJztcbmltcG9ydCB7IFRva2VuRW5kcG9pbnRFcnJvciwgVG9rZW5FbmRwb2ludFVuZXhwZWN0ZWRFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IFRva2Vuc09idGFpbmVkRXZlbnQgfSBmcm9tICcuL2F1dGguZXZlbnRzJztcbmltcG9ydCB7IEV2ZW50c1NlcnZpY2UsIFNpbXBsZU9pZGNJbmZvRXZlbnQgfSBmcm9tICdhbmd1bGFyLXNpbXBsZS1vaWRjL2V2ZW50cyc7XG5cbmludGVyZmFjZSBUb2tlbkVuZHBvaW50UmVzcG9uc2Uge1xuICAgIGFjY2Vzc190b2tlbj86IHN0cmluZztcbiAgICBleHBpcmVzX2luPzogbnVtYmVyO1xuICAgIGlkX3Rva2VuPzogc3RyaW5nO1xuICAgIGVycm9yPzogc3RyaW5nO1xuICAgIHJlZnJlc2hfdG9rZW4/OiBzdHJpbmc7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBUb2tlbkVuZHBvaW50Q2xpZW50U2VydmljZSB7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGh0dHA6IEh0dHBDbGllbnQsXG4gICAgICAgIHByb3RlY3RlZCByZWFkb25seSBkaXNjb3ZlcnlEb2N1bWVudENsaWVudDogT2lkY0Rpc2NvdmVyeURvY0NsaWVudCxcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHRva2VuVmFsaWRhdGlvbjogVG9rZW5WYWxpZGF0aW9uU2VydmljZSxcbiAgICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHRva2VuSGVscGVyOiBUb2tlbkhlbHBlclNlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCByZWFkb25seSBldmVudHM6IEV2ZW50c1NlcnZpY2UsXG4gICAgKSB7IH1cblxuICAgIHB1YmxpYyBjYWxsKHBheWxvYWQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCBoZWFkZXJzOiBIdHRwSGVhZGVycyA9IG5ldyBIdHRwSGVhZGVycygpXG4gICAgICAgICAgICAuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmRpc2NvdmVyeURvY3VtZW50Q2xpZW50LmN1cnJlbnQkXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoeyB0b2tlbl9lbmRwb2ludCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmRpc3BhdGNoKG5ldyBTaW1wbGVPaWRjSW5mb0V2ZW50KGBFeGVjdXRpbmcgVG9rZW4gRW5kcG9pbnRgLFxuICAgICAgICAgICAgICAgICAgICAgICAgeyB1cmw6IHRva2VuX2VuZHBvaW50LCBwYXlsb2FkIH0pKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8VG9rZW5FbmRwb2ludFJlc3BvbnNlPih0b2tlbl9lbmRwb2ludCwgcGF5bG9hZCwgeyBoZWFkZXJzOiBoZWFkZXJzIH0pO1xuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHRhcCh7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiAoZTogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU2ltcGxlT2lkY0Vycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5zdGF0dXMgPT09IDQwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2NzQ5I3NlY3Rpb24tNS4yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFRva2VuRW5kcG9pbnRFcnJvcihlLmVycm9yLmVycm9yLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFRva2VuRW5kcG9pbnRVbmV4cGVjdGVkRXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBtYXAocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXhwaXJlc0F0OiBEYXRlO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuZXhwaXJlc19pbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0F0ID0gdGhpcy50b2tlbkhlbHBlci5nZXRFeHBpcmF0aW9uRnJvbUV4cGlyZXNJbihyZXNwb25zZS5leHBpcmVzX2luKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmRpc3BhdGNoKG5ldyBTaW1wbGVPaWRjSW5mb0V2ZW50KGBUb2tlbiBSZXNwb25zZSBkaWQgbm90IGNvbnRhaW4gZXhwaXJlc19pbmAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGxldCBkZWNvZGVkVG9rZW46IERlY29kZWRJZGVudGl0eVRva2VuO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuaWRfdG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmRpc3BhdGNoKG5ldyBTaW1wbGVPaWRjSW5mb0V2ZW50KGBWYWxpZGF0aW5nIElkZW50aXR5IFRva2VuIGZvcm1hdGAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuaWRfdG9rZW4pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudG9rZW5WYWxpZGF0aW9uLnZhbGlkYXRlSWRUb2tlbkZvcm1hdChyZXNwb25zZS5pZF90b2tlbik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY29kZWRUb2tlbiA9IHRoaXMudG9rZW5IZWxwZXIuZ2V0UGF5bG9hZEZyb21Ub2tlbihyZXNwb25zZS5pZF90b2tlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50cy5kaXNwYXRjaChuZXcgU2ltcGxlT2lkY0luZm9FdmVudChgSWRlbnRpdHkgVG9rZW4gUGF5bG9hZCBkZWNvZGVkYCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVkVG9rZW4pKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmRpc3BhdGNoKG5ldyBTaW1wbGVPaWRjSW5mb0V2ZW50KGBUb2tlbiBSZXNwb25zZSBkaWQgbm90IGNvbnRhaW4gaWRfdG9rZW5gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQ6IFRva2VuUmVxdWVzdFJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY2Vzc1Rva2VuOiByZXNwb25zZS5hY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBhY2Nlc3NUb2tlbkV4cGlyZXNJbjogcmVzcG9uc2UuZXhwaXJlc19pbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY2Vzc1Rva2VuRXhwaXJlc0F0OiBleHBpcmVzQXQgPyBleHBpcmVzQXQuZ2V0VGltZSgpIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiByZXNwb25zZS5lcnJvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkVG9rZW46IHJlc3BvbnNlLmlkX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmcmVzaFRva2VuOiByZXNwb25zZS5yZWZyZXNoX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlZElkVG9rZW46IGRlY29kZWRUb2tlblxuICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRzLmRpc3BhdGNoKG5ldyBUb2tlbnNPYnRhaW5lZEV2ZW50KHJlc3VsdCkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgfVxufVxuIl19