10 min read

How Superset Embedded SDK actually works

guest tokens, RLS, and the config nobody documents in one place

A walkthrough of the official @superset-ui/embedded-sdk: the iframe lifecycle, the guest token flow, row-level security, and every config switch you need to flip.

How Superset Embedded SDK actually works — guest tokens, RLS, and config (social preview)
By Rt Kazakov· Founder · Drafted

Sooner or later most SaaS products need charts inside them, and almost nobody wants to build a query engine and a filter UI from scratch to get there. So you reach for a BI tool. We reach for Apache Superset: SQL-first, open source, no per-seat license. Then you embed it.

The official way in is the @superset-ui/embedded-sdk npm package. It drops a Superset dashboard into a sandboxed, cross-origin <iframe> and handles authorization, messaging, and basic rendering. The pitch is true as far as it goes: a working dashboard in five lines of code. What the readme leaves out is what those five lines actually start. An iframe. A guest-token flow. Row-level security. A config surface that runs well past five lines. We've shipped this in production, so here's the whole machinery before you commit to running it.

The client side: what embedDashboard() actually does

The host application initializes the embed by calling embedDashboard() with a DOM mount point, the Superset domain, the dashboard UUID, and an authentication callback:

import { embedDashboard } from "@superset-ui/embedded-sdk";
 
embedDashboard({
  id: "abc12345-6789-abcd-ef01-23456789abcd", // Dashboard UUID from the Embed modal
  supersetDomain: "https://analytics.example.com",
  mountPoint: document.getElementById("analytics-container"),
  fetchGuestToken: () => fetchTokenFromBackend(),
  dashboardUiConfig: {
    hideTitle: true,
    filters: { expanded: false },
  },
  iframeSandboxExtras: ["allow-top-navigation", "allow-popups-to-escape-sandbox"],
  referrerPolicy: "same-origin",
});

When this executes, six things happen in sequence:

  1. The SDK constructs and mounts an <iframe> inside the designated container.
  2. The iframe's src points at the /embedded/<uuid> route on the Superset server.
  3. To authorize the cross-origin request without a login screen, the SDK calls your fetchGuestToken callback.
  4. The callback fetches a short-lived JWT — the guest token — from your application's backend.
  5. On load, the SDK sets up an HTML5 MessageChannel and instantiates a bidirectional communication layer via the @superset-ui/switchboard package.
  6. The guest token is transmitted over the postMessage channel to authorize the session inside the isolated iframe.

The important architectural fact: from this moment on, everything the user does — filtering, drilling, navigating tabs — happens inside an independent browser context your application cannot see into.

The guest token flow and row-level security

Superset never issues guest tokens directly to client browsers. Your backend acts as a trusted intermediary, executing a server-to-server POST to /api/v1/security/guest_token/, authenticated with a privileged service account. The payload defines a temporary identity, the resources it may access, and optional row-level security clauses:

{
  "user": {
    "username": "customer_user_987",
    "first_name": "Jane",
    "last_name": "Doe"
  },
  "resources": [
    { "type": "dashboard", "id": "abc12345-6789-abcd-ef01-23456789abcd" }
  ],
  "rls": [
    { "clause": "organization_id = 123" }
  ]
}

Superset validates the request, signs the JWT with GUEST_TOKEN_JWT_SECRET, and returns it to your backend, which passes it to the client. When the embedded endpoint receives the token, Superset instantiates an anonymous session mapped to the role configured in GUEST_ROLE_NAME (default: Public). The RLS clauses are compiled and appended to every SQL query the dashboard runs.

Two things about this design bite you later:

  • It is a second authentication system. The guest token has nothing to do with your host application's SSO session. You now operate two parallel auth flows in one browser context.
  • RLS is synthetic. Access rules are evaluated against an anonymous guest role plus whatever clauses your backend injected — not against the real authenticated user's claims.

The full configuration surface

Production setups require coordinated changes across superset_config.py, HTTP headers, and dashboard metadata. This is the complete checklist:

ParameterWherePurposeRequirement
EMBEDDED_SUPERSETsuperset_config.pyFeature flag exposing guest token + embedded endpointsMust be True
GUEST_TOKEN_JWT_SECRETsuperset_config.pySigns and verifies guest JWTsMust be changed from default in production
GUEST_TOKEN_JWT_EXP_SECONDSsuperset_config.pyGuest token validityDefault 300s (5 min)
GUEST_ROLE_NAMEsuperset_config.pyFAB role assigned to guest usersDefault Public, often overridden to Gamma
ENABLE_CORSsuperset_config.pyCross-origin resource sharingMust be True
CORS_OPTIONSsuperset_config.pyAllowed origins, exposed headers, credentialsMust explicitly include host origins with credentials
TALISMAN_CONFIGsuperset_config.pyRelaxes iframe security headersNeeds custom content_security_policy with frame-ancestors
X-Frame-OptionsHTTP header / nginxBlocks iframe rendering by defaultMust be overridden or managed via CSP
Allowed DomainsDashboard metadataRestricts which origins may embed this dashboardChecked against Referer; must be allow-listed

Five lines of client code, nine server-side switches. Most embedding failures we get called about trace back to one of the last four rows — CORS, Talisman, X-Frame-Options, and the per-dashboard allow-list interact in non-obvious ways, especially behind reverse proxies.

Where the architecture stops

Everything above works as documented, and for internal tools, prototypes, and low-stakes reporting the SDK is a perfectly reasonable choice. But the iframe boundary is structural, and no configuration flag crosses it. An isolated cross-origin frame fundamentally cannot:

  • share its filter state with the host application's router or URL;
  • reuse the host's existing SSO session (the guest token is a second, parallel system);
  • adapt to host-controlled CSS or dynamic dark mode without loading flashes;
  • let parent DOM elements render on top of charts, tooltips, or dropdowns;
  • give you editorial control over which dashboards appear for which users without shipping frontend updates.

Each of these turns into a concrete, documented pain point once embedded analytics becomes a real product feature rather than an internal convenience. We collected the six most common failure modes — with the GitHub issues to prove they are not edge cases — in the next article of this series.

If you want to see what dashboards embedded without an iframe look like, the interactive demo on our Superset Embedded page runs the production microfrontend build, and the Superset hub covers the rest of the fork.

Also on X

A shorter, sharper take in article form: x.com/RtKazakov.

Topics

  • Apache Superset
  • Embedded analytics
  • Guest tokens
  • Row-level security
  • Iframe embedding