import { CanceledError } from 'axios'; import { LOGIN_REQUIRED_EVENT } from '../../ajax-handlers-login-required'; import { ReloadHandler } from '../../reload-handler'; import { silentLogin, TokenServerAuthError } from '../../silent-login'; import { WithMicroserviceContext } from '../with-microservice'; import { AuthAdapter } from './auth-adapter'; const MINUTE = 60 * 1000; export interface TokenServerAuthOptions { authInfoURL?: string; onError?: ( defaultErrorHandler: (error: TokenServerAuthError) => void, error: TokenServerAuthError ) => void; } export { TokenServerAuthError } from '../../silent-login'; export class TokenServerAuth implements AuthAdapter { #authAbortController?: AbortController; readonly #context: WithMicroserviceContext; readonly #options: TokenServerAuthOptions; readonly #reloadHandler: ReloadHandler; readonly #loginRequiredHandler: ReloadHandler; constructor(context: WithMicroserviceContext, options: TokenServerAuthOptions = {}) { this.#context = context; this.#options = options; this.#reloadHandler = new ReloadHandler({ id: `token-server-auth-${context.baseURL}` }); this.#loginRequiredHandler = new ReloadHandler({ id: `token-server-auth-login-required`, coolDownInterval: 60 * MINUTE, handler: () => window.dispatchEvent(new CustomEvent(LOGIN_REQUIRED_EVENT)), storage: 'local', }); this.handleError = this.handleError.bind(this); } onDestroy() { this.abortAuthRequest(); } async authenticate() { this.#authAbortController = new AbortController(); try { await silentLogin({ authURL: this.authUrl, authInfoURL: this.#options.authInfoURL, signal: this.#authAbortController.signal, }); this.#reloadHandler.reset(); } catch (error) { if (error instanceof DOMException && error.name === 'AbortError') { throw new CanceledError(); } if (error instanceof TokenServerAuthError) { if (this.#options.onError) { this.#options.onError(this.handleError, error); } else { this.handleError(error); } } throw error; } finally { this.#authAbortController = undefined; } } private get authUrl() { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing return this.#context.authURL || `${this.#context.baseURL}/bff/silent-login`; } private handleError(error: TokenServerAuthError) { if (error.data?.errorCode === 'login_required') { this.#loginRequiredHandler.reload(); } else { this.#reloadHandler.reload(); } } private abortAuthRequest() { if (this.#authAbortController) { this.#authAbortController.abort(); this.#authAbortController = undefined; } } }