Anonymous Access to Tableau Cloud Embedded with Usage Based License and On-Demand Access
Last week, I had an interesting challenge from a client who currently embeds Tableau Public content on their website: “How can I migrate my portfolio of visualizations from Tableau Public to Tableau Cloud while not requiring users to authenticate (i.e., ‘guest’ or ‘anonymous’ access)?”
Historically, the only option would be to self-host your own Tableau Server and license it based on hardware (Core License Model), which can be too expensive for some companies or simply not viable because the company has a cloud-first strategy.
Tableau Cloud and On-Demand Access
Tableau Cloud doesn’t offer unauthenticated access out of the box, but with the introduction of the On-Demand Access (ODA) feature, which allows companies to provide access to embedded Tableau visualizations to an unlimited number of users without the need to pre-provision these users, it has become possible to configure an application to emulate the anonymous access behavior.
This means that now it’s possible to expose Tableau embedded content, which is normally protected behind a login, into public-facing websites without requiring users to authenticate.
The ODA feature is only available on Tableau Cloud and UBL — Usage Based License.
Solution
Since all embedded content hosted in Tableau Cloud requires authentication, the portal where we want the Tableau content to render needs to seamlessly authenticate the embedded session without requiring the user’s input (aka SSO — Single Sign-on).
For that, we’ll leverage the Connected Apps authentication solution, which relies on JSON Web Tokens (JWT). We’ll include two additional claims in the token, to enable on-demand (ephemeral) access:
"https://tableau.com/oda"
: This claim enables the on-demand access capability."https://tableau.com/groups"
: This claim identifies which groups the (ephemeral) user belongs to in Tableau Cloud.
Step 1: Create a Connected App
Start by creating a new Connected App for your application in Tableau Cloud. Notice that you’re restricting access to just the projects where your on-demand content will be saved:
Step 2: Tableau Embed Code (front-end)
Embedding Tableau content is easy, it only takes four lines of code:
<tableau-viz id="tableauViz"
src='https://<your-tableau-cloud-site>/views/my-workbook/my-view'
token="JWT generated from connected app secrets">
</tableau-viz>
Step 3: Generate JWT (back-end)
The back-end of the web portal is responsible for generating the authentication tokens (JWT). Here’s an example of how to generate these JWTs in JavaScript (NodeJs), including the necessary claims to enable on-demand access (and a bonus: optionally pass User Attribute claims):
const jwt = require("jsonwebtoken");
const { v4: uuidv4 } = require("uuid");
function generateJwt() {
// Replace the example values below (remove the brackets).
// Store secrets securely based on your team's best practices.
// See: https://help.tableau.com/current/online/en-us/connected_apps_direct.htm
const secret = "[secretvalue]";
const secretId = "[connectedAppSecretId]";
const clientId = "[connectedAppClientId]";
const scopes = ["tableau:views:embed"];
const userId = "[tableau username]"; //any non-empty string when oda is enabled
const tokenExpiryInMinutes = 1; // Max of 10 minutes.
// ***ENABLE ON-DEMAND ACCESS for "onDemandGroup1" and "onDemandGroup2" ***
const onDemandAccessClaims = {
"[https://tableau.com/oda]": true, //true or false
"[https://tableau.com/groups]": ["onDemandGroup1", "onDemandGroup2"]
}
//*** Optionally pass any number of additional user attribute claims ***
const userAttributes = {
// "[User Attribute Name 1]": "[User Attribute Value]",
// "[User Attribute Name 2]": "[User Attribute Value]"
};
const header = {
alg: "HS256",
typ: "JWT",
kid: secretId,
iss: clientId,
};
const data = {
jti: uuidv4(),
aud: "tableau",
sub: userId,
scp: scopes,
exp: Math.floor(Date.now() / 1000) + tokenExpiryInMinutes * 60,
...onDemandAccessClaims,
...userAttributes,
};
const token = jwt.sign(data, secret, { header });
console.log(token);
}
generateJwt();
Step 4: Create On-Demand Groups
The next step is to create a project where you will save all the content you wish to embed on the public-facing website and grant the necessary permissions to the new on-demand group. You could create multiple on-demand groups with different levels of access. For example:
onDemandGroup1
: Has permissions to export data and PDF.onDemandGroup2
: Doesn't have any export permissions.
The use case is that you might only want to allow people to download the dashboard data for some visualizations, not all. You can leverage these different groups when your application creates the authentication token (JWT) by passing one group or the other.
Step 4: Create Project and Assign Permissions
The next step is to create a project where you will save all the content you wish to embed on the public-facing website and grant the necessary permissions to the new on-demand group(s).
Gotchas with On-Demand Access
While the On-Demand Access feature in Tableau Cloud provides a powerful solution for enabling anonymous access to embedded dashboards, there are a few gotchas to keep in mind:
Disabled User Functions
When On-Demand Access is enabled in the JWT, the following user functions become disabled:
FULLNAME()
ISFULLNAME
ISMEMBEROF
ISUSERNAME
USERDOMAIN()
USERNAME()
Subject Claim (sub
)
The sub
claim (i.e. the username) in the JSON Web Token (JWT) can take any non-empty string value. However, it's essential to set it to a value that your application is aware of because you will still get the traffic usage statistics for every user in the Admin Insights “TS Events” data source.
Let’s look at an example of how I access embedded content when On-Demand Access (ODA) is enabled. In this example, the username “sub” is set to two different values: first, my own email address (a pre-provisioned user on the Tableau Cloud site), and lastly, a random string “blabla”. Note that while ODA is active, the “Actor User Id” field remains null. This is because the user represented by the “sub” claim is ephemeral and doesn’t exist permanently on the site. However, we can still capture the username passed in the “sub” claim through the “Actor User Name” field and track their events.
By following these steps, you can now migrate your portfolio of visualizations from Tableau Public to Tableau Cloud while providing anonymous access to embedded dashboards using the On-Demand Access feature and Usage-Based Licensing (UBL) model.