There is one trap that catches almost everyone. FAB’s Keycloak handler reads a groups claim from the user info endpoint to decide which Superset roles to assign, and a fresh Keycloak client does not include that claim. Logins succeed, everyone gets the default role, and the failure is silent. This guide fixes that in Step 1 so you never see it.
For the general mechanics of Superset authentication, reverse-proxy settings and the break-glass procedure, see our Okta guide; they apply here unchanged. This post covers what is specific to Keycloak. Written against Superset 4.x and Keycloak 24, applicable to Keycloak 17 and later (the versions without the /auth URL prefix).
Step 1: Create the Keycloak client
In the Keycloak admin console, inside the realm your users live in:
- Go to Clients and choose Create client.
- Client type: OpenID Connect. Client ID:
superset. Give it a name and description. Next. - Client authentication: On (this makes it a confidential client with a secret). Authorization: Off. Under Authentication flow, keep Standard flow ticked and untick everything else; Superset only needs the authorization-code flow. Next.
- Root URL:
https://superset.example.com. Valid redirect URIs:https://superset.example.com/oauth-authorized/keycloak. Valid post logout redirect URIs:https://superset.example.com/login/. Web origins:https://superset.example.com. Save. - Open the Credentials tab and copy the Client secret.
The last segment of the redirect URI, keycloak, must match the provider name in superset_config.py.
Add the groups mapper
This is the step that makes role mapping work.
- On the client, open Client scopes and click the dedicated scope named
superset-dedicated. - Choose Add mapper, then By configuration, then Group Membership.
- Name:
groups. Token Claim Name:groups. Full group path: Off (so the claim containssuperset-admins, not/bi/superset-admins). Add to ID token: On. Add to access token: On. Add to userinfo: On. Save.
FAB reads groups from the userinfo endpoint, so “Add to userinfo” is the one that matters. Turning the other two on costs nothing and helps debugging.
If you prefer Keycloak realm roles or client roles to groups, add a User Realm Role or User Client Role mapper instead, with Token Claim Name set to groups so FAB picks it up without a custom security manager. The mapping keys in Superset then become role names rather than group names.
Create groups and assign users
Under Groups, create superset-admins, superset-analysts and superset-viewers, and add users. If Keycloak brokers an upstream directory (LDAP, Active Directory, another OIDC provider), map the upstream groups into these through the identity provider’s mappers, so the Superset-facing group names stay stable even if the upstream changes.
Optionally, restrict who can log in at all: under the client’s Advanced tab, or through a client policy, require membership of a superset-users group. Users outside it are refused by Keycloak, which is preferable to being created in Superset with no useful role.
Step 2: Configure Superset
import os
from flask_appbuilder.security.manager import AUTH_OAUTH
KEYCLOAK_BASE_URL = os.environ["KEYCLOAK_BASE_URL"] # e.g. https://sso.example.com
KEYCLOAK_REALM = os.environ["KEYCLOAK_REALM"] # e.g. corp
KEYCLOAK_REALM_URL = f"{KEYCLOAK_BASE_URL}/realms/{KEYCLOAK_REALM}"
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{
"name": "keycloak",
"icon": "fa-key",
"token_key": "access_token",
"remote_app": {
"client_id": "superset",
"client_secret": os.environ["KEYCLOAK_CLIENT_SECRET"],
"client_kwargs": {"scope": "openid email profile"},
"api_base_url": f"{KEYCLOAK_REALM_URL}/protocol/",
"server_metadata_url": f"{KEYCLOAK_REALM_URL}/.well-known/openid-configuration",
"access_token_url": f"{KEYCLOAK_REALM_URL}/protocol/openid-connect/token",
"authorize_url": f"{KEYCLOAK_REALM_URL}/protocol/openid-connect/auth",
"request_token_url": None,
},
}
]
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Gamma"
# Keycloak group (or role) name -> Superset roles
AUTH_ROLES_MAPPING = {
"superset-admins": ["Admin"],
"superset-analysts": ["Alpha", "sql_lab"],
"superset-viewers": ["Gamma"],
}
AUTH_ROLES_SYNC_AT_LOGIN = True
ENABLE_PROXY_FIX = True
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = "Lax"
Details worth knowing:
- The provider name
keycloakselects FAB’s handler for Keycloak 17 and later. For Keycloak 16 and earlier, whose URLs include/auth/realms/..., use the provider namekeycloak_before_17and add the/authprefix to every URL. api_base_urlends at/protocol/because FAB’s handler requestsopenid-connect/userinforelative to it. Get this wrong and the login completes but the profile fetch 404s.- The
scopedoes not needgroups; the mapper puts groups into userinfo regardless of scope. If you configured the mapper on a separate client scope rather than the dedicated one, add that scope’s name here. - FAB’s Keycloak handler returns
preferred_usernameas the Superset username. Keycloak usernames are stable, so this is a safe default.
Realm roles mapped — now what governs dashboards?
OIDC gets people logged in; role sync, token lifetime, and RBAC design decide what they can see once they’re in. A Superset Architecture Review covers the part after the login screen.
Step 3: Test
Restart Superset and open the login page. You should see a single “Sign in with keycloak” button.
- Log in as a member of
superset-admins. Check Settings, List Users: the user should exist with theAdminrole. - Confirm the groups claim is actually arriving. In Keycloak, open Clients, superset, Client scopes, Evaluate, pick a user and look at Generated user info. The
groupsarray should be present. If it is not, the mapper is on the wrong scope or “Add to userinfo” is off. - Log in as a viewer from a private window and confirm the restricted view.
- Move a user between groups, sign out and in, and confirm the role changes.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Every user gets the Gamma role only | No groups claim in userinfo |
Add the Group Membership mapper with “Add to userinfo” on; check with Client scopes, Evaluate |
Group names in the claim look like /bi/superset-admins |
Full group path is on | Turn it off, or use the full path as the key in AUTH_ROLES_MAPPING |
Invalid parameter: redirect_uri from Keycloak |
Redirect URI not in the client’s valid list, or scheme mismatch | Add the exact URI; enable ENABLE_PROXY_FIX |
404 after login, log mentions userinfo |
api_base_url wrong, usually missing /protocol/ or using the pre-17 /auth prefix |
Correct the URL or switch to keycloak_before_17 |
invalid_client |
Client authentication off (public client), or wrong secret | Turn client authentication on and copy the secret from Credentials |
mismatching_state |
Session cookie not sent on callback | SESSION_COOKIE_SAMESITE = "Lax", SESSION_COOKIE_SECURE matching the scheme |
| Login loops back to Keycloak | Keycloak requires a consent or a required action (update password, verify email) the user has not completed | Complete the action in Keycloak, or disable consent required on the client |
| Works for local Keycloak users, not for brokered users | Upstream identity provider mappers do not populate the groups | Add identity provider mappers to place brokered users into the Superset groups |
Operational notes
- Realm boundaries. Superset can only authenticate users from the realm in its URLs. If different business units live in different realms, either broker them into one realm or configure one provider entry per realm in
OAUTH_PROVIDERS; the login page then shows one button per realm. - Session length. Keycloak’s SSO session settings and Superset’s
PERMANENT_SESSION_LIFETIMEare independent. Disabling a user in Keycloak stops new Superset logins but not the current session; keep Superset’s lifetime short. - Back-channel logout. Keycloak can notify clients when a user logs out centrally. FAB does not consume that notification, so central logout does not end the Superset session. Rely on session lifetime instead.
- Secret rotation. Regenerate the client secret in Keycloak and update Superset’s environment in one change window. There is no grace period for two valid secrets on a single client.
- Air-gapped deployments. Everything here works without internet access. Both Superset and Keycloak must resolve each other’s hostnames, and Superset must trust the certificate Keycloak presents. Mount your internal CA bundle into the Superset container and point
REQUESTS_CA_BUNDLEat it.
Frequently Asked Questions
Why does every Superset user get the Gamma role after Keycloak SSO?
Because the groups claim is missing from the userinfo response. A fresh Keycloak client does not emit it, Flask-AppBuilder finds no role keys, nothing matches AUTH_ROLES_MAPPING, and AUTH_USER_REGISTRATION_ROLE applies to everyone. Add the Group Membership mapper to the client’s dedicated scope with Add to userinfo turned on, then confirm it under Clients, superset, Client scopes, Evaluate before changing anything in Superset.
Which provider name should I use for Keycloak in OAUTH_PROVIDERS?
Use keycloak for Keycloak 17 and later, whose URLs are /realms/<realm>/.... For Keycloak 16 and earlier, use keycloak_before_17 and add the /auth prefix to every URL. The provider name also has to match the last segment of the redirect URI registered on the client, so changing one means changing the other.
Can Superset authenticate users from more than one Keycloak realm?
Not through a single provider entry, because the realm is baked into the URLs. Either broker the other directories into one realm through Keycloak’s identity provider mappers, which is the cleaner option, or add one entry per realm to OAUTH_PROVIDERS. The second approach puts one sign-in button per realm on the Superset login page, which users find confusing beyond two.
Does Keycloak back-channel logout end the Superset session?
No. Keycloak can notify clients when a user logs out centrally, but Flask-AppBuilder does not consume that notification, so a central logout leaves the Superset session running until it expires. The same applies to disabling a user: new logins stop immediately, the current session does not. Keep PERMANENT_SESSION_LIFETIME to a working day or less and treat it as the real revocation window.
Build It With Andolasoft
Once Superset trusts Keycloak, the role mapping above becomes the front door to everything else: which roles reach which datasets, how row-level security narrows them, and who gets SQL Lab. A Superset Architecture Review looks at authentication, RBAC and RLS together, alongside caching, async queries and upgrade readiness, and delivers a written report in five working days. For a self-hosted platform that stays patched and monitored without your team on call, air-gapped deployments included, see Managed Support, and for the wider set of controls, our post on governance and security for Superset deployments.
If you are running Keycloak in front of a self-hosted Superset and the group mapping has never quite been right, talk to us. We will trace a real login end to end, show you where the claim is being lost, and give you a fixed-scope plan for the role model behind it.