UNPKG

ashish-sdk

Version:
201 lines 7.77 kB
import { initMixpanel } from './mixpanel-service'; import { AuthType, EmbedEvent } from './types'; import { appendToUrlHash } from './utils'; // eslint-disable-next-line import/no-cycle import { fetchSessionInfoService, fetchAuthTokenService, fetchAuthService, fetchBasicAuthService, } from './utils/authService'; // eslint-disable-next-line import/no-mutable-exports export let loggedInStatus = false; // eslint-disable-next-line import/no-mutable-exports export let samlAuthWindow = null; // eslint-disable-next-line import/no-mutable-exports export let samlCompletionPromise = null; // eslint-disable-next-line import/no-mutable-exports export let sessionInfo = null; export const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b'; export const EndPoints = { AUTH_VERIFICATION: '/callosum/v1/session/info', SAML_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`, OIDC_LOGIN_TEMPLATE: (targetUrl) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`, TOKEN_LOGIN: '/callosum/v1/session/login/token', BASIC_LOGIN: '/callosum/v1/session/login', }; /** * Check if we are logged into the ThoughtSpot cluster * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP */ async function isLoggedIn(thoughtSpotHost) { const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`; let response = null; try { response = await fetchSessionInfoService(authVerificationUrl); } catch (e) { return false; } return response.status === 200; } /** * Return sessionInfo if available else make a loggedIn check to fetch the sessionInfo */ export function getSessionInfo() { return sessionInfo; } export function initSession(sessionDetails) { sessionInfo = sessionDetails; initMixpanel(sessionInfo); } /** * Check if we are stuck at the SSO redirect URL */ function isAtSSORedirectUrl() { return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0; } /** * Remove the SSO redirect URL marker */ function removeSSORedirectUrlMarker() { // Note (sunny): This will leave a # around even if it was not in the URL // to begin with. Trying to remove the hash by changing window.location will reload // the page which we don't want. We'll live with adding an unnecessary hash to the // parent page URL until we find any use case where that creates an issue. window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, ''); } /** * Perform token based authentication * @param embedConfig The embed configuration */ export const doTokenAuth = async (embedConfig) => { const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig; if (!authEndpoint && !getAuthToken) { throw new Error('Either auth endpoint or getAuthToken function must be provided'); } const loggedIn = await isLoggedIn(thoughtSpotHost); if (!loggedIn) { let authToken = null; if (getAuthToken) { authToken = await getAuthToken(); } else { const response = await fetchAuthTokenService(authEndpoint); authToken = response.text(); } await fetchAuthService(thoughtSpotHost, username, authToken); loggedInStatus = false; } loggedInStatus = true; }; /** * Perform basic authentication to the ThoughtSpot cluster using the cluster * credentials. * * Warning: This feature is primarily intended for developer testing. It is * strongly advised not to use this authentication method in production. * @param embedConfig The embed configuration */ export const doBasicAuth = async (embedConfig) => { const { thoughtSpotHost, username, password } = embedConfig; const loggedIn = await isLoggedIn(thoughtSpotHost); if (!loggedIn) { const response = await fetchBasicAuthService(thoughtSpotHost, username, password); loggedInStatus = response.status === 200; } loggedInStatus = true; }; async function samlPopupFlow(ssoURL) { document.body.insertAdjacentHTML('beforeend', '<div id="ts-saml-auth"></div>'); const authElem = document.getElementById('ts-saml-auth'); samlCompletionPromise = samlCompletionPromise || new Promise((resolve, reject) => { window.addEventListener('message', (e) => { if (e.data.type === EmbedEvent.SAMLComplete) { e.source.close(); resolve(); } }); }); authElem.addEventListener('click', () => { if (samlAuthWindow === null || samlAuthWindow.closed) { samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes'); } else { samlAuthWindow.focus(); } }, { once: true }); authElem.click(); return samlCompletionPromise; } /** * Perform SAML authentication * @param embedConfig The embed configuration */ const doSSOAuth = async (embedConfig, ssoEndPoint) => { const { thoughtSpotHost } = embedConfig; const loggedIn = await isLoggedIn(thoughtSpotHost); if (loggedIn) { if (isAtSSORedirectUrl()) { removeSSORedirectUrlMarker(); } loggedInStatus = true; return; } // we have already tried authentication and it did not succeed, restore // the current URL to the original one and invoke the callback. if (isAtSSORedirectUrl()) { removeSSORedirectUrlMarker(); loggedInStatus = false; return; } const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`; if (embedConfig.noRedirect) { await samlPopupFlow(ssoURL); return; } window.location.href = ssoURL; }; export const doSamlAuth = async (embedConfig) => { const { thoughtSpotHost } = embedConfig; // redirect for SSO, when the SSO authentication is done, this page will be loaded // again and the same JS will execute again. const ssoRedirectUrl = embedConfig.noRedirect ? `${thoughtSpotHost}/v2/#/embed/saml-complete` : appendToUrlHash(window.location.href, SSO_REDIRECTION_MARKER_GUID); // bring back the page to the same URL const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`; await doSSOAuth(embedConfig, ssoEndPoint); }; export const doOIDCAuth = async (embedConfig) => { const { thoughtSpotHost } = embedConfig; // redirect for SSO, when the SSO authentication is done, this page will be loaded // again and the same JS will execute again. const ssoRedirectUrl = embedConfig.noRedirect ? `${thoughtSpotHost}/v2/#/embed/saml-complete` : appendToUrlHash(window.location.href, SSO_REDIRECTION_MARKER_GUID); // bring back the page to the same URL const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`; await doSSOAuth(embedConfig, ssoEndPoint); }; /** * Perform authentication on the ThoughtSpot cluster * @param embedConfig The embed configuration */ export const authenticate = async (embedConfig) => { const { authType } = embedConfig; switch (authType) { case AuthType.SSO: return doSamlAuth(embedConfig); case AuthType.OIDC: return doOIDCAuth(embedConfig); case AuthType.AuthServer: return doTokenAuth(embedConfig); case AuthType.Basic: return doBasicAuth(embedConfig); default: return Promise.resolve(); } }; /** * Check if we are authenticated to the ThoughtSpot cluster */ export const isAuthenticated = () => loggedInStatus; //# sourceMappingURL=auth.js.map