Hi all,
We’re piloting an embedded analytics approach for our HMIS: rather than pushing data back into DHIS2 (we’ve been hitting issues with category combos and append-only data pushes requiring full delete/re-upload cycles), we’re embedding Apache Superset dashboards directly into the DHIS2 Dashboard app, sourcing data from our own SQL Server warehouse.
Setup:
- DHIS2 instance with a custom Spring Boot integration service that requests Superset guest tokens for embedding (via
/api/v1/security/guest_token/), passing a Row Level Security (RLS) clause dynamically per user based on their assigned DHIS2 org unit(s). - Users can be assigned org units at national, regional, or facility level, and some users have multiple facility assignments.
- We’ve built an
OrgUnitHierarchyPathcolumn into our Superset dataset (e.g.OUNESWATINI/OURegHHOHHO/OUFcltyH001) so a singleLIKE '%<org_unit_code>%'filter can match at any level of the hierarchy.
The problem:
When accessing the dashboard directly in Superset (own login, no guest token), the dataset and charts return data correctly. But when the same dashboard is embedded in DHIS2 via a guest token — with the dynamic RLS clause attached — every chart shows “No data,” even for a user assigned to the top-level national org unit, which should match every row.
There is no static rule configured under Settings → Row Level Security in Superset — the RLS filtering is being injected entirely at guest-token request time by our backend service, which logs confirmation that it’s building and attaching the clause (e.g. Set org unit hierarchy RLS for user: 'Sakhile', org units: 'OUNESWATINI') before requesting the token.
What we’ve ruled out so far:
- The underlying SQL query returns data correctly when run directly (confirmed in SQL Lab).
- The dataset/chart definitions match what’s expected — no stale dataset pointer.
- Not a caching issue — confirmed via force refresh.
- Not a static RLS rule — none exists.
This points to the issue being in how the guest-token RLS clause itself is constructed or transmitted, but we wanted to check whether anyone in the community has:
- Implemented a similar DHIS2-org-unit-to-Superset-RLS integration before, and if so, what clause format / guest token payload structure worked for you.
- Encountered a similar “works logged in directly, fails via guest token” pattern, and what turned out to be the cause.
- Any guidance on the exact expected format Superset’s guest token
rlsarray expects (e.g. does theclauseneed to reference the dataset’s column exactly as named, any quoting/escaping gotchas, dataset ID scoping per RLS entry, etc.)