UNPKG

oidc-client-rx

Version:

ReactiveX enhanced OIDC and OAuth2 protocol support for browser-based JavaScript applications

136 lines (135 loc) 7.74 kB
import { HttpHeaders } from "@ngify/http"; import { Injectable, inject } from "injection-js"; import { of, throwError } from "rxjs"; import { catchError, concatMap, retry, switchMap } from "rxjs/operators"; import { DataService } from "../api/data.service.js"; import { ResetAuthDataService } from "../flows/reset-auth-data.service.js"; import { CheckSessionService } from "../iframe/check-session.service.js"; import { LoggerService } from "../logging/logger.service.js"; import { StoragePersistenceService } from "../storage/storage-persistence.service.js"; import { removeNullAndUndefinedValues } from "../utils/object/object.helper.js"; import { RedirectService } from "../utils/redirect/redirect.service.js"; import { UrlService } from "../utils/url/url.service.js"; function _ts_decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : null === desc ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) r = Reflect.decorate(decorators, target, key, desc); else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } class LogoffRevocationService { logoff(config, allConfigs, logoutAuthOptions) { if (!config) return throwError(()=>new Error("Please provide a configuration before setting up the module")); this.loggerService.logDebug(config, "logoff, remove auth", logoutAuthOptions); const { urlHandler, customParams } = logoutAuthOptions || {}; const endSessionUrl = this.urlService.getEndSessionUrl(config, customParams); if (!endSessionUrl) { this.loggerService.logDebug(config, "No endsessionUrl present. Logoff was only locally. Returning."); return of(null); } if (this.checkSessionService.serverStateChanged(config)) { this.loggerService.logDebug(config, "Server State changed. Logoff was only locally. Returning."); return of(null); } if (urlHandler) { this.loggerService.logDebug(config, `Custom UrlHandler found. Using this to handle logoff with url '${endSessionUrl}'`); urlHandler(endSessionUrl); this.resetAuthDataService.resetAuthorizationData(config, allConfigs); return of(null); } return this.logoffInternal(logoutAuthOptions, endSessionUrl, config, allConfigs); } logoffLocal(config, allConfigs) { this.resetAuthDataService.resetAuthorizationData(config, allConfigs); this.checkSessionService.stop(); } logoffLocalMultiple(allConfigs) { allConfigs.forEach((configuration)=>{ this.logoffLocal(configuration, allConfigs); }); } logoffAndRevokeTokens(config, allConfigs, logoutAuthOptions) { if (!config) return throwError(()=>new Error("Please provide a configuration before setting up the module")); const { revocationEndpoint } = this.storagePersistenceService.read("authWellKnownEndPoints", config) || {}; if (!revocationEndpoint) { this.loggerService.logDebug(config, "revocation endpoint not supported"); return this.logoff(config, allConfigs, logoutAuthOptions); } if (this.storagePersistenceService.getRefreshToken(config)) return this.revokeRefreshToken(config).pipe(switchMap((_)=>this.revokeAccessToken(config)), catchError((error)=>{ const errorMessage = "revoke token failed"; this.loggerService.logError(config, errorMessage, error); return throwError(()=>new Error(errorMessage)); }), concatMap(()=>this.logoff(config, allConfigs, logoutAuthOptions))); return this.revokeAccessToken(config).pipe(catchError((error)=>{ const errorMessage = "revoke accessToken failed"; this.loggerService.logError(config, errorMessage, error); return throwError(()=>new Error(errorMessage)); }), concatMap(()=>this.logoff(config, allConfigs, logoutAuthOptions))); } revokeAccessToken(configuration, accessToken) { if (!configuration) return throwError(()=>new Error("Please provide a configuration before setting up the module")); const accessTok = accessToken || this.storagePersistenceService.getAccessToken(configuration); const body = this.urlService.createRevocationEndpointBodyAccessToken(accessTok, configuration); return this.sendRevokeRequest(configuration, body); } revokeRefreshToken(configuration, refreshToken) { if (!configuration) return throwError(()=>new Error("Please provide a configuration before setting up the module")); const refreshTok = refreshToken || this.storagePersistenceService.getRefreshToken(configuration); const body = this.urlService.createRevocationEndpointBodyRefreshToken(refreshTok, configuration); return this.sendRevokeRequest(configuration, body); } logoffInternal(logoutAuthOptions, endSessionUrl, config, allConfigs) { const { logoffMethod, customParams } = logoutAuthOptions || {}; if (!logoffMethod || "GET" === logoffMethod) { this.redirectService.redirectTo(endSessionUrl); this.resetAuthDataService.resetAuthorizationData(config, allConfigs); return of(null); } const { state, logout_hint, ui_locales } = customParams || {}; const { clientId } = config; const idToken = this.storagePersistenceService.getIdToken(config); const postLogoutRedirectUrl = this.urlService.getPostLogoutRedirectUrl(config); const headers = this.getHeaders(); const { url } = this.urlService.getEndSessionEndpoint(config); const body = { id_token_hint: idToken, client_id: clientId, post_logout_redirect_uri: postLogoutRedirectUrl, state, logout_hint, ui_locales }; const bodyWithoutNullOrUndefined = removeNullAndUndefinedValues(body); this.resetAuthDataService.resetAuthorizationData(config, allConfigs); return this.dataService.post(url, bodyWithoutNullOrUndefined, config, headers); } sendRevokeRequest(configuration, body) { const url = this.urlService.getRevocationEndpointUrl(configuration); const headers = this.getHeaders(); return this.dataService.post(url, body, configuration, headers).pipe(retry(2), switchMap((response)=>{ this.loggerService.logDebug(configuration, "revocation endpoint post response: ", response); return of(response); }), catchError((error)=>{ const errorMessage = "Revocation request failed"; this.loggerService.logError(configuration, errorMessage, error); return throwError(()=>new Error(errorMessage)); })); } getHeaders() { let headers = new HttpHeaders(); headers = headers.set("Content-Type", "application/x-www-form-urlencoded"); return headers; } constructor(){ this.loggerService = inject(LoggerService); this.dataService = inject(DataService); this.storagePersistenceService = inject(StoragePersistenceService); this.urlService = inject(UrlService); this.checkSessionService = inject(CheckSessionService); this.resetAuthDataService = inject(ResetAuthDataService); this.redirectService = inject(RedirectService); } } LogoffRevocationService = _ts_decorate([ Injectable() ], LogoffRevocationService); export { LogoffRevocationService };