Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/authToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ const storeAuthTokenInCache = (token: string): void => {
*
* @param embedConfig
*/
export async function getAuthenticationToken(embedConfig: EmbedConfig): Promise<string> {
export async function getAuthenticationToken(embedConfig: EmbedConfig, getFreshToken: boolean = false): Promise<string> {
const cachedAuthToken = getCacheAuthToken();
// Since we don't have token validation enabled , we cannot tell if the
// cached token is valid or not. So we will always fetch a new token.
if (cachedAuthToken && !embedConfig.disableTokenVerification) {
if (cachedAuthToken && !embedConfig.disableTokenVerification && !getFreshToken) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why. have we added this to the normal flow ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using the same function for the refresh token as well, but since the token is not yet expired incase of refresh call, it sends the same cached token, add this flag to skip the cache check.

let isCachedTokenStillValid;
try {
isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
Expand Down
2 changes: 1 addition & 1 deletion src/embed/ts-embed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4055,7 +4055,7 @@ describe('Destroy error handling', () => {
}).not.toThrow();

expect(logSpy).toHaveBeenCalledWith('Error destroying TS Embed', expect.any(Error));
logSpy.mockRestore();
logSpy.mockReset();
});
});

Expand Down
26 changes: 25 additions & 1 deletion src/embed/ts-embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ export class TsEmbed {
this.embedConfig.customVariablesForThirdPartyTools || {},
hiddenListColumns: this.viewConfig.hiddenListColumns || [],
customActions: customActionsResult.actions,
embedExpiryInAuthToken: this.viewConfig.refreshAuthTokenOnNearExpiry,
...getInterceptInitData(this.viewConfig),
};

Expand Down Expand Up @@ -507,6 +508,28 @@ export class TsEmbed {
}
};

/**
* Refresh the auth token if the autoLogin is true and the authType is TrustedAuthTokenCookieless
* @param _
* @param responder
*/
private tokenRefresh = async (_: any, responder: any) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better type safety and code clarity, consider providing specific types for the _ and responder parameters instead of any. Based on the on method signature, _ can be typed as MessagePayload and responder as (data: any) => void. You'll need to import MessagePayload from ../types.

Suggested change
private tokenRefresh = async (_: any, responder: any) => {
private tokenRefresh = async (_: MessagePayload, responder: (data: any) => void) => {

const { authType, autoLogin } = this.embedConfig;
const isAutoLoginTrue = autoLogin ?? (authType === AuthType.TrustedAuthTokenCookieless);
if (isAutoLoginTrue && authType === AuthType.TrustedAuthTokenCookieless) {
try {
const authToken = await getAuthenticationToken(this.embedConfig, true);
responder({
type: EmbedEvent.RefreshAuthToken,
data: { authToken },
});
} catch (e) {
logger.error(`${ERROR_MESSAGE.INVALID_TOKEN_ERROR} Error : ${e?.message}`);
processAuthFailure(e, this.isPreRendered ? this.preRenderWrapper : this.el);
}
Comment on lines +520 to +529
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This try...catch block is nearly identical to the one in the updateAuthToken method (lines 544-553). To improve code maintainability and adhere to the DRY (Don't Repeat Yourself) principle, consider extracting this logic into a shared private helper method. This helper could take parameters for getFreshToken and the EmbedEvent type to handle the minor differences between the two usages.

}
}

/**
* Sends updated auth token to the iFrame to avoid user logout
* @param _
Expand Down Expand Up @@ -569,9 +592,10 @@ export class TsEmbed {

const embedListenerReadyHandler = this.createEmbedContainerHandler(EmbedEvent.EmbedListenerReady);
this.on(EmbedEvent.EmbedListenerReady, embedListenerReadyHandler, { start: false }, true);

const authInitHandler = this.createEmbedContainerHandler(EmbedEvent.AuthInit);
this.on(EmbedEvent.AuthInit, authInitHandler, { start: false }, true);
this.on(EmbedEvent.RefreshAuthToken, this.tokenRefresh, { start: false }, true);
};

/**
Expand Down
27 changes: 27 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,20 @@ export interface BaseViewConfig extends ApiInterceptFlags {
* ```
*/
customActions?: CustomAction[];


/**
* Refresh the auth token when the token is near expiry.
* @version SDK: 1.43.0 | ThoughtSpot: 10.14.0.cl
* @example
* ```js
* const embed = new AppEmbed('#tsEmbed', {
* ... // other embed view config
* refreshAuthTokenOnNearExpiry: true,
* })
* ```
*/
refreshAuthTokenOnNearExpiry?: boolean;
}

/**
Expand Down Expand Up @@ -3149,6 +3163,19 @@ export enum EmbedEvent {
* @version SDK: 1.43.0 | ThoughtSpot: 10.15.0.cl
*/
ApiIntercept = 'ApiIntercept',

/**
* @hidden
* Emitted when the auth token is about to get expired and needs to be refreshed.
* @example
* ```js
* embed.on(EmbedEvent.RefreshAuthToken, (payload) => {
* console.log('payload', payload);
* })
* ```
* @version SDK: 1.45.0 | ThoughtSpot: 26.2.0.cl
*/
RefreshAuthToken = 'RefreshAuthToken',
}

/**
Expand Down
Loading
Loading