Skip to content

Commit

Permalink
SCAL-227728 - Updated sso marker to differ from hash paths (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbhanu-thoughtspot authored Oct 11, 2024
1 parent e83649a commit 5a1540a
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 25 deletions.
18 changes: 15 additions & 3 deletions src/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as SessionService from './utils/sessionInfoService';
const thoughtSpotHost = 'http://localhost:3000';
const username = 'tsuser';
const password = '12345678';
const samalLoginUrl = `${thoughtSpotHost}/callosum/v1/saml/login?targetURLPath=%235e16222e-ef02-43e9-9fbd-24226bf3ce5b`;
const samalLoginUrl = `${thoughtSpotHost}/callosum/v1/saml/login?targetURLPath=%23%3FtsSSOMarker%3D5e16222e-ef02-43e9-9fbd-24226bf3ce5b`;

export const embedConfig: any = {
doTokenAuthSuccess: (token: string) => ({
Expand Down Expand Up @@ -331,8 +331,8 @@ describe('Unit test for auth', () => {
spyOn(checkReleaseVersionInBetaInstance, 'checkReleaseVersionInBeta');
Object.defineProperty(window, 'location', {
value: {
href: authInstance.SSO_REDIRECTION_MARKER_GUID,
hash: '',
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(
Expand All @@ -348,6 +348,12 @@ describe('Unit test for auth', () => {
});

it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
Object.defineProperty(window, 'location', {
value: {
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
expect(window.location.hash).toBe('');
Expand Down Expand Up @@ -401,6 +407,12 @@ describe('Unit test for auth', () => {
});

it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
Object.defineProperty(window, 'location', {
value: {
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
await authInstance.doOIDCAuth(embedConfig.doOidcAuth);
expect(window.location.hash).toBe('');
Expand Down
10 changes: 7 additions & 3 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { initMixpanel } from './mixpanel-service';
import {
AuthType, DOMSelector, EmbedConfig, EmbedEvent,
} from './types';
import { getDOMNode, getRedirectUrl } from './utils';
import { getDOMNode, getRedirectUrl, getSSOMarker } from './utils';
import {
EndPoints,
fetchAuthPostService,
Expand Down Expand Up @@ -245,7 +245,7 @@ export function getReleaseVersion() {
* Check if we are stuck at the SSO redirect URL
*/
function isAtSSORedirectUrl(): boolean {
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
return window.location.href.indexOf(getSSOMarker(SSO_REDIRECTION_MARKER_GUID)) >= 0;
}

/**
Expand All @@ -257,7 +257,11 @@ function removeSSORedirectUrlMarker(): void {
// 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, '');

// Replace any occurences of ?ssoMarker=guid or &ssoMarker=guid.
let updatedHash = window.location.hash.replace(`?${getSSOMarker(SSO_REDIRECTION_MARKER_GUID)}`, '');
updatedHash = updatedHash.replace(`&${getSSOMarker(SSO_REDIRECTION_MARKER_GUID)}`, '');
window.location.hash = updatedHash;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/css-variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export interface CustomCssVariables {
/**
* Font color of the text on toggle buttons such as
* **All**, **Answers**, and **Liveboards** on the Home page (Classic experience),
* the text color of the chart and table tiles on Home page (New modular Homepage experience),
* and title text on the AI-generated charts and tables.
* the text color of the chart and table tiles on Home page (New modular Homepage
* experience), and title text on the AI-generated charts and tables.
* The default color code is #2770EF.
*
*/
Expand Down
3 changes: 0 additions & 3 deletions src/embed/liveboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ export interface LiveboardViewConfig
*
* Since, this will show preview images, be careful that it may show
* undesired data to the user when using row level security.
*
* @example
* ```js
* const embed = new LiveboardEmbed('#embed-container', {
Expand All @@ -280,7 +279,6 @@ export interface LiveboardViewConfig
* });
* embed.render();
* ```
*
* @version SDK: 1.32.0 | ThoughtSpot: 10.0.0.cl
*/
showPreviewLoader?: boolean;
Expand Down Expand Up @@ -613,7 +611,6 @@ export class LiveboardEmbed extends V1Embed {
/**
* Returns the full url of the liveboard/viz which can be used to open
* this liveboard inside the full Thoughtspot application in a new tab.
*
* @returns url string
*/
public getLiveboardUrl(): string {
Expand Down
1 change: 0 additions & 1 deletion src/tokenizedFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { AuthType } from './types';
* Fetch wrapper that adds the authentication token to the request.
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
* The interface for this method is the same as Web `Fetch`.
*
* @param input
* @param init
* @example
Expand Down
12 changes: 6 additions & 6 deletions src/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ describe('unit test for utils', () => {

test('appendToUrlHash', () => {
expect(appendToUrlHash('http://myhost:3000', 'hashFrag')).toBe(
'http://myhost:3000#hashFrag',
'http://myhost:3000#?tsSSOMarker=hashFrag',
);
expect(appendToUrlHash('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foobar');
expect(appendToUrlHash('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foo?tsSSOMarker=bar');
});

describe('getRedirectURL', () => {
Expand All @@ -135,9 +135,9 @@ describe('unit test for utils', () => {

test('Should return correct value when path is undefined', () => {
expect(getRedirectUrl('http://myhost:3000', 'hashFrag')).toBe(
'http://myhost:3000#hashFrag',
'http://myhost:3000#?tsSSOMarker=hashFrag',
);
expect(getRedirectUrl('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foobar');
expect(getRedirectUrl('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foo?tsSSOMarker=bar');
});

test('Should return correct value when path is set', () => {
Expand All @@ -148,11 +148,11 @@ describe('unit test for utils', () => {
}));

expect(getRedirectUrl('http://myhost:3000/', 'hashFrag', '/bar')).toBe(
'http://myhost:3000/bar#hashFrag',
'http://myhost:3000/bar#?tsSSOMarker=hashFrag',
);

expect(getRedirectUrl('http://myhost:3000/#/foo', 'hashFrag', '#/bar')).toBe(
'http://myhost:3000/#/barhashFrag',
'http://myhost:3000/#/bar?tsSSOMarker=hashFrag',
);
});
});
Expand Down
16 changes: 14 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ export const getCssDimension = (value: number | string): string => {
return value;
};

export const getSSOMarker = (markerId: string) => {
const encStringToAppend = encodeURIComponent(markerId);
return `tsSSOMarker=${encStringToAppend}`;
};

/**
* Append a string to a URL's hash fragment
* @param url A URL
Expand All @@ -140,11 +145,18 @@ export const appendToUrlHash = (url: string, stringToAppend: string) => {
let outputUrl = url;
const encStringToAppend = encodeURIComponent(stringToAppend);

const marker = `tsSSOMarker=${encStringToAppend}`;

let splitAdder = '';

if (url.indexOf('#') >= 0) {
outputUrl = `${outputUrl}${encStringToAppend}`;
// If second half of hash contains a '?' already add a '&' instead of
// '?' which appends to query params.
splitAdder = url.split('#')[1].indexOf('?') >= 0 ? '&' : '?';
} else {
outputUrl = `${outputUrl}#${encStringToAppend}`;
splitAdder = '#?';
}
outputUrl = `${outputUrl}${splitAdder}${marker}`;

return outputUrl;
};
Expand Down
1 change: 0 additions & 1 deletion src/utils/processData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export function processCustomAction(e: any, thoughtSpotHost: string) {

/**
* Responds to AuthInit sent from host signifying successful authentication in host.
*
* @param e
* @returns {any}
*/
Expand Down
4 changes: 0 additions & 4 deletions src/utils/sessionInfoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ let sessionInfo: null | SessionInfo = null;
* Returns the session info object and caches it for future use.
* Once fetched the session info object is cached and returned from the cache on
* subsequent calls.
*
* @example ```js
* const sessionInfo = await getSessionInfo();
* console.log(sessionInfo);
Expand All @@ -40,7 +39,6 @@ export async function getSessionInfo(): Promise<SessionInfo> {
/**
* Returns the cached session info object. If the client is not authenticated the
* function will return null.
*
* @example ```js
* const sessionInfo = getCachedSessionInfo();
* if (sessionInfo) {
Expand All @@ -58,7 +56,6 @@ export function getCachedSessionInfo(): SessionInfo | null {

/**
* Processes the session info response and returns the session info object.
*
* @param sessionInfoResp {any} Response from the session info API.
* @returns {SessionInfo} The session info object.
* @example ```js
Expand Down Expand Up @@ -87,7 +84,6 @@ export const getSessionDetails = (sessionInfoResp: any): SessionInfo => {

/**
* Resets the cached session info object and forces a new fetch on the next call.
*
* @example ```js
* resetCachedSessionInfo();
* const sessionInfo = await getSessionInfo();
Expand Down

0 comments on commit 5a1540a

Please sign in to comment.