GitHub user FrancescoCastaldi added a comment to the discussion: Superset -
Clarification regarding support for multiple tenants
In Apache Superset 6.x, multi-tenancy where a single user dynamically switches
organization context is achieved through one of two proven architectures:
### Architecture 1: Embedded SDK with Scoped Guest Tokens (Recommended)
If users access Superset embedded inside your host application portal, the host
application manages the active organization context.
When the user switches organizations in your application's dropdown:
1. Your backend issues a guest token (`/api/v1/security/guest_token/`) scoped
specifically to:
- The active dashboard IDs allowed for that organization.
- An explicit Row Level Security (RLS) clause restricting data queries to
that organization:
```json
{
"user": {"username": "john.doe", "first_name": "John", "last_name": "Doe"},
"resources": [{"type": "dashboard", "id": "<dashboard_uuid>"}],
"rls": [{"clause": "organization_id = 'ORG_A'"}]
}
```
2. Your frontend calls `embedDashboard()` with the new token.
3. Dashboards and data from other organizations remain completely inaccessible,
and context switches happen seamlessly without modifying global user roles.
### Architecture 2: Custom Security Manager with Dynamic Session Context
(Standalone UI)
If users log directly into the standalone Superset web interface:
Superset does not have an out-of-the-box organization switcher in its top
navbar, but its security layer is fully extensible via
`CUSTOM_SECURITY_MANAGER` in `superset_config.py`.
1. **Store Active Context in Flask Session:**
Implement a custom view or API endpoint `/set_tenant/<org_id>` that stores
`session["active_tenant_id"] = org_id`.
2. **Dynamic RLS Filter Injection:**
In `superset_config.py`, write a custom Jinja macro that injects the active
tenant ID into dataset queries:
```python
# In superset_config.py
from flask import session
def get_active_tenant():
return session.get("active_tenant_id", "DEFAULT_ORG")
JINJA_CONTEXT_ADDONS = {
"current_tenant": get_active_tenant
}
```
In your datasets, add a filter clause:
```sql
organization_id = '{{ current_tenant() }}'
```
3. **Dashboard Visibility via DASHBOARD_RBAC:**
Enable `DASHBOARD_RBAC: True` in `FEATURE_FLAGS`. For the 1 dashboard specific
to Organization A, assign a dedicated role `Role_Org_A`. In your custom
security manager, dynamically append `Role_Org_A` to `g.user.roles` only when
`session["active_tenant_id"] == "Org_A"`.
GitHub link:
https://github.com/apache/superset/discussions/42373#discussioncomment-19164781
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]