oidc-client-rx
Version:
ReactiveX enhanced OIDC and OAuth2 protocol support for browser-based JavaScript applications
105 lines (104 loc) • 5.72 kB
JavaScript
import { Injectable, inject } from "injection-js";
import { of, throwError } from "rxjs";
import { catchError, switchMap, tap } from "rxjs/operators";
import { AuthStateService } from "../../auth-state/auth-state.service.js";
import { DOCUMENT } from "../../dom/index.js";
import { LoggerService } from "../../logging/logger.service.js";
import { StoragePersistenceService } from "../../storage/storage-persistence.service.js";
import { ValidationResult } from "../../validation/validation-result.js";
import { FlowsDataService } from "../flows-data.service.js";
import { ResetAuthDataService } from "../reset-auth-data.service.js";
import { SigninKeyDataService } from "../signin-key-data.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;
}
const JWT_KEYS = "jwtKeys";
class HistoryJwtKeysCallbackHandlerService {
callbackHistoryAndResetJwtKeys(callbackContext, config, allConfigs) {
let toWrite = {
...callbackContext.authResult
};
if (!this.responseHasIdToken(callbackContext)) {
const existingIdToken = this.storagePersistenceService.getIdToken(config);
toWrite = {
...toWrite,
id_token: existingIdToken
};
}
this.storagePersistenceService.write("authnResult", toWrite, config);
if (config.allowUnsafeReuseRefreshToken && callbackContext.authResult?.refresh_token) this.storagePersistenceService.write("reusable_refresh_token", callbackContext.authResult.refresh_token, config);
if (this.historyCleanUpTurnedOn(config) && !callbackContext.isRenewProcess) this.resetBrowserHistory();
else this.loggerService.logDebug(config, "history clean up inactive");
if (callbackContext.authResult?.error) {
const errorMessage = `AuthCallback AuthResult came with error: ${callbackContext.authResult.error}`;
this.loggerService.logDebug(config, errorMessage);
this.resetAuthDataService.resetAuthorizationData(config, allConfigs);
this.flowsDataService.setNonce("", config);
this.handleResultErrorFromCallback(callbackContext.authResult, callbackContext.isRenewProcess);
return throwError(()=>new Error(errorMessage));
}
this.loggerService.logDebug(config, `AuthResult '${JSON.stringify(callbackContext.authResult, null, 2)}'.
AuthCallback created, begin token validation`);
return this.signInKeyDataService.getSigningKeys(config).pipe(tap((jwtKeys)=>this.storeSigningKeys(jwtKeys, config)), catchError((err)=>{
const storedJwtKeys = this.readSigningKeys(config);
if (storedJwtKeys) {
this.loggerService.logWarning(config, "Failed to retrieve signing keys, fallback to stored keys");
return of(storedJwtKeys);
}
return throwError(()=>new Error(err));
}), switchMap((jwtKeys)=>{
if (jwtKeys) {
callbackContext.jwtKeys = jwtKeys;
return of(callbackContext);
}
const errorMessage = "Failed to retrieve signing key";
this.loggerService.logWarning(config, errorMessage);
return throwError(()=>new Error(errorMessage));
}), catchError((err)=>{
const errorMessage = `Failed to retrieve signing key with error: ${err}`;
this.loggerService.logWarning(config, errorMessage);
return throwError(()=>new Error(errorMessage));
}));
}
responseHasIdToken(callbackContext) {
return !!callbackContext?.authResult?.id_token;
}
handleResultErrorFromCallback(result, isRenewProcess) {
let validationResult = ValidationResult.SecureTokenServerError;
if (result && "object" == typeof result && "error" in result && "login_required" === result.error) validationResult = ValidationResult.LoginRequired;
this.authStateService.updateAndPublishAuthState({
isAuthenticated: false,
validationResult,
isRenewProcess
});
}
historyCleanUpTurnedOn(config) {
const { historyCleanupOff } = config;
return !historyCleanupOff;
}
resetBrowserHistory() {
this.document.defaultView?.history.replaceState({}, this.document.title, this.document.defaultView.location.origin + this.document.defaultView.location.pathname);
}
storeSigningKeys(jwtKeys, config) {
this.storagePersistenceService.write(JWT_KEYS, jwtKeys, config);
}
readSigningKeys(config) {
return this.storagePersistenceService.read(JWT_KEYS, config);
}
constructor(){
this.loggerService = inject(LoggerService);
this.authStateService = inject(AuthStateService);
this.flowsDataService = inject(FlowsDataService);
this.signInKeyDataService = inject(SigninKeyDataService);
this.storagePersistenceService = inject(StoragePersistenceService);
this.resetAuthDataService = inject(ResetAuthDataService);
this.document = inject(DOCUMENT);
}
}
HistoryJwtKeysCallbackHandlerService = _ts_decorate([
Injectable()
], HistoryJwtKeysCallbackHandlerService);
export { HistoryJwtKeysCallbackHandlerService };