Embedding Superset Dashboards: Guest Token and RLS
We encountered a situation: a client – a fintech startup with 5 departments (sales, marketing, finance, HR, support). Each department wanted to see its own analytics on a common BI portal, but data was strictly segregated. Apache Superset is a powerful open-source tool, but out of the box it cannot be embedded into a third-party application without additional setup. Without proper configuration of Guest Token and Row Level Security (RLS), dashboards either see all data or fail to load due to CORS errors. We solved the problem by embedding Superset via Embedded SDK, and now we share our experience. Setup took 3 days; the result – each department sees only its own metrics, and IT manages access centrally. Savings on licenses compared to paid BI solutions can range from 300,000 to 500,000 rubles per year.
What problems does embedding Superset solve?
The main pain point is data segregation between departments. Without RLS, we had to create separate dashboards for each department, increasing development time by 2 weeks and making the system inflexible. Superset with Embedded SDK allows embedding one dashboard and dynamically filtering data via Guest Token. Additionally, we solve:
- CORS errors – incorrect configuration blocks dashboard loading.
- Access management – centralized via your application.
- Performance – average dashboard load time reduced by 40% after cache configuration.
How does embedding via Embedded SDK work?
Superset uses the Embedded SDK and Guest Token for secure embedding. The Guest Token is a temporary JWT key linked to a user and dashboard. As stated in the official Superset documentation: Guest Token is a time-limited JWT used for embedding dashboards securely. We configure an endpoint in our application that issues the token via the Superset API. Unlike Metabase, where you need to set up a JWT proxy, Superset allows passing RLS conditions directly in the token. This provides flexibility: data is filtered at the SQL query level.
Superset Configuration
In superset_config.py:
FEATURE_FLAGS = {
"EMBEDDED_SUPERSET": True,
"ENABLE_TEMPLATE_PROCESSING": True
}
CORS_OPTIONS = {
'supports_credentials': True,
'origins': ['https://your-app.com']
}
SESSION_COOKIE_SAMESITE = None
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
Key points: EMBEDDED_SUPERSET enables embedding; CORS – only your domain; cookies SameSite=None are required for iframes.
Additional CORS options
If your frontend is on a subdomain, specify it in `origins`. For production, add `'methods': ['GET', 'POST']` and `'allow_headers': ['Content-Type', 'Authorization']`.Guest Token Generation
async function getSupersetGuestToken(
dashboardId: string,
userId: string,
userEmail: string
): Promise<string> {
// Get admin access token
const loginResponse = await fetch(`${SUPERSET_URL}/api/v1/security/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: process.env.SUPERSET_ADMIN_USER,
password: process.env.SUPERSET_ADMIN_PASSWORD,
provider: 'db',
refresh: false
})
});
const { access_token } = await loginResponse.json();
// Get Guest Token for a specific dashboard
const guestResponse = await fetch(`${SUPERSET_URL}/api/v1/security/guest_token/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${access_token}`
},
body: JSON.stringify({
user: {
username: userId,
first_name: userEmail.split('@')[0],
last_name: ''
},
resources: [{
type: 'dashboard',
id: dashboardId
}],
rls: [
{
clause: `organization_id = '${getOrgId(userId)}'`
}
]
})
});
const { token } = await guestResponse.json();
return token;
}
Note: we use rls with a dynamic organization_id. This guarantees that users from different companies will not see each other's data.
React Component via SDK
npm install @superset-ui/embedded-sdk
import { embedDashboard } from '@superset-ui/embedded-sdk';
import { useEffect, useRef } from 'react';
function SupersetDashboard({ dashboardId }) {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!containerRef.current) return;
const embed = embedDashboard({
id: dashboardId,
supersetDomain: process.env.NEXT_PUBLIC_SUPERSET_URL,
mountPoint: containerRef.current,
fetchGuestToken: () =>
fetch(`/api/superset/guest-token?dashboardId=${dashboardId}`)
.then(r => r.json())
.then(d => d.token),
dashboardUiConfig: {
hideTitle: true,
hideTab: false,
filters: {
expanded: false
}
}
});
return () => embed.unmount();
}, [dashboardId]);
return (
<div ref={containerRef}
className="superset-container w-full rounded-xl overflow-hidden"
style={{ height: '600px' }}
/>
);
}
The component can be reused for any dashboard – just pass the ID.
How to configure Row Level Security?
Through rls in the Guest Token, queries in Superset are automatically filtered at the SQL level. Superset adds WHERE organization_id = 'user-org-id' to each query. The user physically cannot see data of other organizations. This is an alternative to configuring separate roles in Superset – we manage access centrally from our application. In one project, RLS reduced the time for access segregation from two weeks to two days.
When to choose Superset over Metabase?
| Criterion | Superset | Metabase |
|---|---|---|
| Embedding | Embedded SDK + Guest Token | JWT proxy or paid plan |
| RLS | Via Guest Token (at SQL level) | Configured within Metabase |
| License | Apache 2.0 (free) | AGPL (Enterprise paid) |
| Performance | Slower on complex queries | Faster for simple dashboards |
Superset wins in customization flexibility and cost – license savings compared to paid BI can range from 300,000 to 500,000 rubles per year. If you need simple analytics without complex RLS, Metabase is easier to set up. But for deep customization and data segregation, Superset is the optimal choice.
Process and timeline
- Analysis – we study your dashboards and user roles.
- Superset configuration – CORS, Guest Token, RLS setup.
- Backend development – endpoint for token issuance (usually Node.js or Django).
- SDK integration – embedding component into React/Vue/Angular.
- Testing – verification of access rights and loading.
- Deployment – CI/CD and monitoring setup.
| Stage | Duration |
|---|---|
| Analysis | 1 day |
| Superset configuration | 1 day |
| Backend development | 1–2 days |
| SDK integration | 1 day |
| Testing | 1 day |
| Deployment | 0.5 day |
As a result, you get configuration documentation, an API for token issuance, an RLS schema, ready component code, and team training. Support for 2 weeks after launch.
Typical embedding mistakes
- Ignoring CORS – dashboard does not load. Ensure
origincontains the exact application domain including protocol. - Incorrect
SameSitefor cookies – if not set toNone, the iframe will block cookies. - Wrong RLS conditions – without validation, users may see others' data. Always verify that the
clauseis substituted correctly. - No handling of Guest Token expiration – the token has a limited lifetime (default 30 minutes). Set up automatic refresh on the client side.
Contact us – we will assess your project in 1 day and offer the optimal solution. Order Superset setup with a ready security module and get a consultation on integration with any framework.







