Create an embed API with JSON Web Tokens (Beta)

🚩

This is a public beta feature that’s subject to quick, iterative changes. As a result, the latest product version may differ from the contents of this document. For more information, see Beta features.

Sigma supports authenticating secure embeds using JSON Web Tokens (JWTs). JWTs offer a secure way to embed content that can be accessed by both external users (users who do not have a registered account in Sigma) and internal users (users who access Sigma directly through their Sigma account).

Signing your secure embed URLs with JWTs has several advantages:

  • JWTs are compact, URL-safe tokens that can be digitally signed, ensuring that the data they contain is tamper-proof.
  • Embed developers no longer have to use the Sigma UI to generate embed paths; they may use the URL instead.
  • Embedding workbooks, pages, and individual visualizations is supported.
  • JWT-signed embed URLs can authenticate internal Sigma users to access embedded content with the same email address they use for their Sigma account.
  • When using JWT-signed URLs, you have the option to disable automatic embed user account provisioning for non-Sigma users, effectively restricting your embed content to the users you have explicitly provisioned in Sigma or your IdP.

📘

Existing embed customers are likely familiar with Sigma’s “signed URL” embed-API, which uses a nonce to ensure that the constructed URL is one-time use only. Similarly, JWTs are one-time use. When a JWT is issued, the jti claim, a unique identifier for the token, is stored server-side. When the JWT is used (e.g., to access an embedded Sigma dashboard), the server checks whether the jti has already been seen. If it has, the token is rejected as a replay attempt, ensuring it cannot be reused.

Limitations

  • Most embed URL parameters are not currently supported in JWT-signed embed URLs.
  • Only admins will be able to impersonate other users (including embed users). Non-admins can only log in as themselves.
  • You cannot test JWT-signed embed URLs in the embed sandbox.

Authentication flow

This diagram shows the interaction between the end user browser, the client front end, client back end, and Sigma. Step 1, the end user loads the client application and logs in. Step 2, the front end requests a JWT. Step 3, the back end responds with JWT signed with client secret. Step 4, client front end loads app.sigmacomputing.com/<org-slug>?:jwt=<jwt>. Step 5, Sigma authenticates user and returns content based on the JWT.

JWT claims

Claim nameRequired?Claim descriptionType
subRequiredThe email address of the user logging in.string
jtiRequiredJWT ID. A unique ID associated with the session.string
iatRequiredIssued at time, as number of seconds from epoch.number
expRequiredExpired at time, as number of seconds from epoch. Cannot exceed 30 days.number
oauth_tokenOptionalThe OAuth token to use when using OAuth connections. This token must be encrypted with the embed secret.string
eval_connection_idOptionalThe connection to use instead of the connection that the workbook is associated with.string
first_nameOptional, affects embed users only.First name for the embed user.string
last_nameOptional, affects embed users only.Last name for the embed user.string
user_attributesOptional, affects embed users only.User attributes for the embed user.Record<string,string>
account_typeOptional, affects embed users only.Account type for the embed user.string
teamsOptional, affects embed users only.Teams that the embed user is a part of.string[]

Example script to generate a JWT-signed secure embed URL

The following script demonstrates how to programmatically generate a secure embed URL signed with a JWT.

The script makes use of an environment file for some required values. In a production environment, these values would be generated dynamically by the parent application. See Generate embed client credentials for instructions on how to generate the embed client id and secret.

# .env file

# Sigma embed configuration - REQUIRED parameters:
EMBED_URL={url path to embed}
EMBED_CLIENT_ID={your client id}
EMBED_SECRET=(your embed secret)
[email protected] 

What URL to use

This method requires a URL path to be provided in the signing process. The URL syntax varies depending on whether you are embedding a workbook, a page, or a single element.

WorkbookNavigate to the workbook that you intend to embed, ensure it is in Published mode, and copy the URL directly from the browser without altering the syntax.

Example URL syntax for a workbook:
https://app.sigmacomputing.com/{organization-name}/workbook/{workbookname}-{workbookUrlId}
PageSelect the desired workbook page, then copy the URL and edit it to follow the example syntax.

Example URL syntax for a page:
https://app.sigmacomputing.com/{organization-name}/workbook/{workbookname}-{workbookUrlId}/page/{pageId}
Single elementSelect the desired workbook element, then copy the URL and edit it, following the example syntax.

Example URL syntax for a single element:
https://app.sigmacomputing.com/{organization-name}/workbook/{workbookname}-{workbookUrlId}/element/{elementId}

Example server-side embed API with JWT

A few optional parameters in the script below have been hard-coded (account_type and teams). These would also be dynamically generated at runtime by the parent application.

const jwt = require('jsonwebtoken'); // Import jsonwebtoken library for handling JWTs
const { v4: uuid } = require('uuid'); // Import uuid for generating unique identifiers
const dotenv = require('dotenv'); // Import dotenv for loading environment variables

dotenv.config(); // Load environment variables from .env file

// Define constants for the embed URL and session length
const EMBED_URL = process.env.EMBED_URL;
const SESSION_LENGTH = Math.min(process.env.SESSION_LENGTH || 3600, 2592000); // Max 30 days in seconds

// Log important configuration details to ensure they are correctly set
console.log('EMBED_URL:', EMBED_URL);
console.log('SESSION_LENGTH:', SESSION_LENGTH);
console.log('EMBED_CLIENT_ID:', process.env.EMBED_CLIENT_ID); // Verify the client ID

// Function to generate a signed URL for embedding Sigma dashboards
async function generateSignedUrl() {
    try {
        // Retrieve the secret and email from environment variables
        const secret = process.env.EMBED_SECRET;
        const email = process.env.EMBED_EMAIL;
        const time = Math.floor(Date.now() / 1000); // Generate the current time as a Unix timestamp

        // Generate JWT with claims
        // See https://help.sigmacomputing.com/docs/create-an-embed-api-with-json-web-tokens for list of available claims
        const token = jwt.sign({
            sub: email, // Subject (the email of the user)
            iss: process.env.EMBED_CLIENT_ID, // Issuer (client ID)
            jti: uuid(), // JWT ID (unique identifier for the token)
            iat: time, // Issued at time (current time)
            exp: time + SESSION_LENGTH, // Expiration time (current time + session length)
            account_type: "lite", // Optional claim for account type
            teams: ["Sales_People"] // Optional claim for user teams
        }, secret, {
            algorithm: 'HS256', // Algorithm used for signing the JWT
            keyid: process.env.EMBED_CLIENT_ID // Key ID for the JWT header, should match Sigma's expectations
        });

        // Decode the JWT to inspect its content and log it
        const decodedToken = jwt.decode(token, { complete: true });
        console.log('Decoded JWT:', decodedToken); // Log the decoded JWT for debugging

        // Construct the signed embed URL by appending the JWT and embed parameters
        const signedEmbedUrl = `${EMBED_URL}?:jwt=${token}&:embed=true`;

        // Log the constructed signed URL
        console.log('Signed Embed URL:', signedEmbedUrl);

        return signedEmbedUrl; // Return the signed embed URL
    } catch (error) {
        // Log any errors that occur during JWT generation
        console.error("Failed to generate JWT:", error);
        throw new Error("JWT generation failed"); // Throw an error if JWT generation fails
    }
}

// Export the generateSignedUrl function so it can be used in other files
module.exports = { generateSignedUrl };

The resulting "signedEmbedUrl" follows this structure: <https://app.sigmacomputing.com/><org-slug>?:jwt={JWT VALUE}&:embed=true

For a detailed discussion and demonstration of using JWT when embedding Sigma, see the QuickStart: Secure Embedding with JWT. The QuickStart uses a sample project stored in GitHub.

Configure access to your embedded content authenticated with JWTs

When using JWT-signed URLs for your secure embeds, you have the option to disable automatic embed user account creation and update for non-Sigma users. If you choose to disable this default behavior, you can restrict your embed content to the users you have explicitly provisioned in Sigma or your IdP. By default, automatic user creation is enabled, and Sigma will automatically create embed users and assign them to the team you specify in the teams claim, and will update those embed user team assignments if new teams are passed in the teams claim.

📘

This setting has no effect for embedded content that is not authenticated with JWT-signed URLs.

To disable automatic embed user account provisioning and updates, follow these steps:

  1. Go to Administration > Embeds.
  2. Click Settings.
  3. Turn off the Automatic user creation toggle.

When automatic user creation is disabled, Sigma shows an error message when a user who has not explicitly been granted access to that content in Sigma attempts to access embedded content using a JWT-signed URL.

This error message also occurs for users who have been provisioned with a Sigma account but have never logged in. To avoid this error for those users, ensure that any users who will need access to JWT-authenticated embedded content log into Sigma at least once before attempting to access the embedded content.