• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thoughtspot / visual-embed-sdk / #2519

27 Sep 2025 11:43AM UTC coverage: 94.115% (-0.02%) from 94.133%
#2519

Pull #315

shivam-kumar-ts
SCAL-255099 Enhance error handling for authentication token
Pull Request #315: SCAL-255099 Enhance error handling for authentication token

1230 of 1390 branches covered (88.49%)

Branch coverage included in aggregate %.

3 of 4 new or added lines in 1 file covered. (75.0%)

39 existing lines in 2 files now uncovered.

2976 of 3079 relevant lines covered (96.65%)

84.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.97
/src/authToken.ts
1
import { ERROR_MESSAGE } from './errors';
26✔
2
import { EmbedConfig } from './types';
3
import { getValueFromWindow, storeValueInWindow, formatTemplate } from './utils';
26✔
4
import { fetchAuthTokenService, verifyTokenService } from './utils/authService/authService';
26✔
5
import { logger } from './utils/logger';
26✔
6

7
const cacheAuthTokenKey = 'cachedAuthToken';
26✔
8

9
const getCacheAuthToken = (): string | null => getValueFromWindow(cacheAuthTokenKey);
47✔
10
const storeAuthTokenInCache = (token: string): void => {
26✔
11
    storeValueInWindow(cacheAuthTokenKey, token);
297✔
12
};
13

14
// This method can be used to get the authToken using the embedConfig
15
/**
16
 *
17
 * @param embedConfig
18
 */
19
export async function getAuthenticationToken(embedConfig: EmbedConfig): Promise<string> {
26✔
20
    const cachedAuthToken = getCacheAuthToken();
27✔
21
    // Since we don't have token validation enabled , we cannot tell if the
22
    // cached token is valid or not. So we will always fetch a new token.
23
    if (cachedAuthToken && !embedConfig.disableTokenVerification) {
27✔
24
        let isCachedTokenStillValid;
25
        try {
3✔
26
            isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
3✔
27
        } catch {
28
            isCachedTokenStillValid = false;
1✔
29
        }
30

31
        if (isCachedTokenStillValid) return cachedAuthToken;
3✔
32
    }
33

34
    const { authEndpoint, getAuthToken } = embedConfig;
25✔
35

36
    let authToken = null;
25✔
37
    if (getAuthToken) {
25✔
38
        try{
23✔
39
            authToken = await getAuthToken();
23✔
40
        } catch (e) {
41
            logger.error(e.message);
8✔
NEW
UNCOV
42
            throw e;
×
43
        }
44
    } else {
45
        const response = await fetchAuthTokenService(authEndpoint);
2✔
46
        authToken = await response.text();
2✔
47
    }
48

49
    try {
17✔
50
        // this will throw error if the token is not valid
51
        await validateAuthToken(embedConfig, authToken);
17✔
52
    } catch (e) {
53
        logger.error(`${ERROR_MESSAGE.INVALID_TOKEN_ERROR} Error : ${e.message}`);
2✔
54
        throw e;
2✔
55
    }
56

57
    storeAuthTokenInCache(authToken);
15✔
58
    return authToken;
15✔
59
}
60

61
export const validateAuthToken = async (
26✔
62
    embedConfig: EmbedConfig,
63
    authToken: string,
64
    suppressAlert?: boolean,
65
): Promise<boolean> => {
66
    // even if token verification is disabled, we will still validate
67
    // that the token is a string before proceeding.
68
    if (typeof authToken !== 'string') {
22✔
69
        const errorMessage = formatTemplate(ERROR_MESSAGE.INVALID_TOKEN_TYPE_ERROR, {
2✔
70
            invalidType: typeof authToken,
71
        });
72
        logger.error(errorMessage);
2✔
73
        throw new Error(errorMessage);
2✔
74
    }
75

76
    const cachedAuthToken = getCacheAuthToken();
20✔
77

78
    if (embedConfig.disableTokenVerification) {
20✔
79
        logger.info('Token verification is disabled. Assuming token is valid.');
1✔
80
        return true;
1✔
81
    }
82
    try {
19✔
83
        const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
19✔
84
        if (isTokenValid) return true;
19✔
85
    } catch {
UNCOV
86
        return false;
×
87
    }
88

89
    if (cachedAuthToken && cachedAuthToken === authToken) {
3✔
90
        if (!embedConfig.suppressErrorAlerts && !suppressAlert) {
2✔
91
            // eslint-disable-next-line no-alert
92
            alert(ERROR_MESSAGE.DUPLICATE_TOKEN_ERR);
1✔
93
        }
94
        throw new Error(ERROR_MESSAGE.DUPLICATE_TOKEN_ERR);
2✔
95
    } else {
96
        throw new Error(ERROR_MESSAGE.INVALID_TOKEN_ERROR);
1✔
97
    }
98
};
99

100
/**
101
 * Resets the auth token and a new token will be fetched on the next request.
102
 * @example
103
 * ```js
104
 * resetCachedAuthToken();
105
 * ```
106
 * @version SDK: 1.28.0 | ThoughtSpot: *
107
 * @group Authentication / Init
108
 */
109
export const resetCachedAuthToken = (): void => {
26✔
110
    storeAuthTokenInCache(null);
282✔
111
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc