UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

120 lines (119 loc) • 4.46 kB
import { SHORTLINK_PARAMETER } from '../share/iurlshortener.js'; export default class AbstractConnectManager { storagePath = 'oAuth'; urlParameterForHash = 'hash'; context; constructor(context) { this.context = context; } get state() { return this.context.stateManager.state; } loggedOutFromBackend() { this.context.errorManager.pushMessage('You were logged out', 'Your identity is not recognized any more by the backend. Please try to login again, or contact an administrator.', 'warning'); this.loggedOut(); } handleErrorFromIssuer() { this.context.errorManager.pushMessage('Login Failed', this.state.oauth.error ?? 'Unknown error', 'error'); this.loggedOut(); } handleUnknownError(error) { this.state.oauth.error = error.message; this.state.oauth.status = 'loginFailed'; } loggedOut(saveState = true) { if (saveState) { this.context.sessionManager.saveStateToSession(); } this.state.oauth.status = 'loggedOut'; this.state.oauth.tokens = undefined; this.state.oauth.userInfo = undefined; this.state.oauth.audience = []; } /** * The RedirectUrl has to be the same for all call to the issuer * Because the authentication is given for a specific redirectUrl. * Therefore, we keep it in localStorage. */ get redirectUrl() { return this.loadFromLocalStorage('redirectUrl'); } set redirectUrl(value) { this.saveToLocalStorage('redirectUrl', value); } getLoginRedirectUrl(silent) { let url; if (silent) { url = new URL(this.context.urlManager.getRootUrl()); url.pathname += 'silentlogincallback.html'; } else { url = new URL(this.context.urlManager.getBaseUrlPath()); } url.searchParams.append('authentified', 'true'); this.preserveUrlHash(url); return url.toString(); } getLogoutRedirectUrl() { if (this.context.configManager.Config.oauth?.issuer.customLogoutRedirectUrl) { return this.context.configManager.Config.oauth?.issuer.customLogoutRedirectUrl; } const url = new URL(this.context.urlManager.getBaseUrlPath()); url.searchParams.append('authentified', 'false'); this.preserveUrlHash(url); return url.toString(); } /** * Save the URL hash to a query parameter since some OIDC providers don't allow URL hashes in the redirect URL */ preserveUrlHash(url) { const hash = this.context.urlManager.getHash(); if (hash?.length && hash !== 'session') { console.error('App state in URL!!!'); } if (hash) { url.searchParams.append(this.urlParameterForHash, hash); } } restoreUrlHash(url) { const urlHash = this.context.urlManager.getParam(this.urlParameterForHash); if (urlHash) { url.hash = urlHash; } } loadFromLocalStorage(path) { return this.context.userDataManager.getFromLocalStorage(`${this.storagePath}.${path}`) ?? ''; } saveToLocalStorage(path, value) { this.context.userDataManager.saveToLocalStorage(`${this.storagePath}.${path}`, value); } resetUrl() { const url = new URL(this.context.urlManager.getBaseUrlPath()); // Keep the short link: the shared state is restored only after the login workflow const shortId = this.context.urlManager.getParam(SHORTLINK_PARAMETER); if (shortId) { url.searchParams.set(SHORTLINK_PARAMETER, shortId); } this.restoreUrlHash(url); this.context.urlManager.updateUrl(url); } finalizeLoginWorkflow() { switch (this.state.oauth.status) { case 'loggedIn': this.resetUrl(); break; case 'loggedOut': this.resetUrl(); break; case 'not-initialized': case 'backend.loggedOut': case 'issuer.loggedIn': case 'loginFailed': case 'logoutFailed': throw new Error('We should only finalize the login workflow when the user is either loggedIn or loggedOut'); default: throw new Error('Unmanaged login state'); } this.state.application.isAuthInitialized = true; } }