Skip to content
Merged
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
90 changes: 47 additions & 43 deletions modules/ROOT/pages/trusted-auth-sdk.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ When `init()` is called, the SDK checks if there is an existing ThoughtSpot sess

Cookieless authentication, specified using `AuthType.TrustedAuthTokenCookieless`, uses the token as a bearer token for all subsequent requests to ThoughtSpot, without establishing a session in the browser.

Cookie-based authentication, specified using `AuthType.TrustedAuthToken`, uses the token to create a session in the browser immediately, and does not use the token afterward, instead relying on the established session with the ThoughtSpot instance.
Cookie-based authentication, specified using `AuthType.TrustedAuthToken`, uses the token to create a session in the browser immediately. It does not use the token afterward; instead, it relies on the established session with the ThoughtSpot instance.

For the request to be *secure*, the user in the browser cannot modify the request or make their own valid request to the *token request service* in a way that requests a token for any other user.

The `autoLogin: true` property in the `init()` function causes the Visual Embed SDK to request a new token before the current token or the session expires, so that a user never sees the embedded ThoughtSpot component in a signed-out state.

== Define token request service
There are two options in the `init()` function to define the request to the *token request service*: `authEndpoint` or `getAuthToken`.

Expand All @@ -25,9 +27,9 @@ The `authEndpoint` parameter of the `init()` function specifies a URL for a dire

Any authentication details must be included by the browser in this automated GET request, typically in the cookies.

It is *insecure* to allow specifying the username of the desired login token in the URL called by `authEndpoint`, because any user could request tokens for other users. Instead, the *token request service* itself must be able to determine which user is logged in from the backend.
It is *insecure* to allow specifying the username of the desired login token in the URL called by `authEndpoint`, because any user could request tokens for other users. Instead, the *token request service* must determine the logged-in user from the backend.

Cookies are not sent across domains (only to sub-domains), so your *token request service* must be *hosted in the same domain* as the embedding application.
Cookies are not sent across domains (only to subdomains), so your *token request service* must be *hosted in the same domain* as the embedding application.

If you need more control beyond a GET request, use `getAuthToken` instead to define a customized request.

Expand All @@ -40,8 +42,8 @@ The callback function must return a *Promise* that resolves with the *login toke
----
init({
thoughtSpotHost: "<%=tshost%>",
authType: AuthType.TrustedAuthToken,
username: "UserA",
authType: AuthType.TrustedAuthTokenCookieless,
autoLogin: true,
getAuthToken: () => {
// fetch() returns a Promise naturally. Assumes a JSON response from the token request service with a 'token' property
return fetch('https://my-backend.app/ts-token')
Expand All @@ -51,14 +53,13 @@ init({
});
----

You can even use the callback function to reference a hard-coded login token, in a testing or other appropriate situation. Remember, it must return a Promise that resolves with the token:
You can even use the callback function to reference a hard-coded login token in a testing or other appropriate situation. Remember, it must return a Promise that resolves with the token:

[source,JavaScript]
----
init({
thoughtSpotHost: "<%=tshost%>",
authType: AuthType.TrustedAuthToken,
username: "<username>",
authType: AuthType.TrustedAuthTokenCookieless,
getAuthToken: () => {
let tsToken = '{long-lived-token}';
return Promise.resolve(tsToken);
Expand Down Expand Up @@ -90,7 +91,7 @@ The Visual Embed SDK provides a link:https://developers.thoughtspot.com/docs/Fun
Please see the documentation on xref:rest-apiv2-js.adoc[REST API V2.0 within a browser] for further explanation and example code.

=== Multiple user sessions in one browser
Cookieless authentication is also useful for scenarios where the embedding application allows for being logged into multiple user accounts in different tabs, or quick switches between users. Cookie-based authentication restricts the whole browser to a single logged-in user per ThoughtSpot instance, while cookie-less allows each tab to use a different token without conflicts.
Cookieless authentication is also useful for scenarios where the embedding application allows for being logged into multiple user accounts in different tabs, or quick switches between users. Cookie-based authentication restricts the whole browser to a single logged-in user per ThoughtSpot instance, while cookieless allows each tab to use a different token without conflicts.

== Code examples
The only difference between cookie-based trusted authentication and cookieless authentication in the `init()` function is the value used for the `authType` property.
Expand All @@ -104,38 +105,39 @@ The following example shows a custom callback function with a custom request usi
let tsToken; // global scope to store token for other REST API requests
init({
thoughtSpotHost: tsURL,
authType: AuthType.TrustedAuthTokenCookieless,
getAuthToken: getAuthToken
});
authType: AuthType.TrustedAuthTokenCookieless,
getAuthToken: getAuthToken,
autoLogin: true
});

function async getAuthToken {
const tokenURL = tokenServiceURL + "/gettoken/";
console.log("calling token server at " + tokenURL);

const timeoutSecs = 5 * 1000; // seconds to milliseconds

const response = await timeout(timeoutSecs, fetch(
tokenURL,
{
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
// This Token Request Service returns the token as a plain-text string
'Content-Type': "text/plain",
// Custom header for passing a JWT with auth details from the web app to the token request service
// Instead the token request service may have access to a user session with the details
'X-Auth-Token': authJWT
},
credentials: 'include'
}
))

// Token request service returns plain-text string of the token
// set the global tsToken variable for using the token for separate REST API requests
tsToken = response.text();
// Must return for the Promise to be completed
return response.text()
const tokenURL = tokenServiceURL + "/gettoken/";
console.log("calling token server at " + tokenURL);

const timeoutSecs = 5 * 1000; // seconds to milliseconds

const response = await timeout(
timeoutSecs,
fetch(tokenURL, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
// This Token Request Service returns the token as a plain-text string
'Content-Type': "text/plain",
// Custom header for passing a JWT with auth details from the web app to the token request service
// Instead the token request service may have access to a user session with the details
'X-Auth-Token': authJWT
},
credentials: 'include'
})
)

// Token request service returns plain-text string of the token
// set the global tsToken variable for using the token for separate REST API requests
tsToken = response.text();
// Must return for the Promise to be completed
return response.text()
}
----

Expand All @@ -146,8 +148,8 @@ function async getAuthToken {
init({
thoughtSpotHost: "<ThoughtSpot-Host-URL>",
authType: AuthType.TrustedAuthToken,
username: "<username>",
authEndpoint: "https://authenticator-server:<port>/endpoint",
autoLogin: true
});
----

Expand All @@ -156,12 +158,12 @@ init({
init({
thoughtSpotHost: "<ThoughtSpot-Host-URL>",
authType: AuthType.TrustedAuthToken,
username: "<username>",
autoLogin: true,
getAuthToken: () => {
return fetch('https://my-backend.app/ts-token')
.then((response) => response.json())
.then((data) => data.token);
});
});
----

=== Cookieless authentication examples
Expand All @@ -172,6 +174,7 @@ init({
thoughtSpotHost: "<ThoughtSpot-Host-URL>",
authType: AuthType.TrustedAuthTokenCookieless,
authEndpoint: "https://authenticator-server:<port>/endpoint",
autoLogin: true
});
----

Expand All @@ -181,10 +184,11 @@ init({
init({
thoughtSpotHost: "<ThoughtSpot-Host-URL>",
authType: AuthType.TrustedAuthTokenCookieless,
autoLogin: true,
getAuthToken: () => {
return fetch('https://my-backend.app/ts-token')
.then((response) => response.json())
.then((data) => data.token);
}
});
});
----
Loading