GitHub user dosubot[bot] added a comment to the discussion: Questions regarding OAuth token management and session handling in Apache Superset
<!-- Answer --> Here's what I found regarding your questions about OAuth token management and session handling in Superset: **1. Is the access token saved by Superset in the session?** Yes and no. When you log in via OAuth, the token response from Zitadel is captured in Flask-AppBuilder's (FAB) internal session during the OAuth callback. However, Superset **does not expose or persist this token for application use by default**. What you see in the browser is Superset's own encrypted Flask session cookie — this is the standard behavior [[1]](https://github.com/apache/superset/pull/38469). **2. Standard behavior: cookie-only approach** Yes, this is the standard way Superset handles OAuth sessions. Superset's user authentication OAuth (powered by Flask-AppBuilder) is designed purely to **authenticate the user into Superset**. After login, Superset manages its own session via a Flask session cookie. It does **not** persist the external provider's access token on the client side or make it readily available for custom API calls [[2]](https://github.com/apache/superset/blob/829e4d92d91ceae4b43b1ed3b063ffe45377799c/superset/security/manager.py). **3. Token expiration and session independence** You're correct — if the Zitadel token expires after 12 hours but the Superset session cookie is still valid, the user remains logged into Superset. The Superset session lifetime is independent of the OAuth provider's token lifetime. Superset only uses the OAuth token at login time to verify identity and create/update the user. **4. Token refresh — not automatic for user auth tokens (currently)** Superset does **not** automatically refresh user authentication OAuth tokens out of the box. The automatic refresh mechanism that exists in Superset is for **database OAuth2 tokens** (a separate system for authenticating queries to databases like Trino or Google Sheets), not for user login tokens [[3]](https://github.com/apache/superset/blob/829e4d92d91ceae4b43b1ed3b063ffe45377799c/superset/utils/oauth2.py). **5. How to access the Zitadel token for your custom API** There is a pending feature (PR [#38469](https://github.com/apache/superset/pull/38469)) that introduces **upstream OAuth token forwarding**. It allows you to configure `"save_token": True` in your `OAUTH_PROVIDERS` config, which saves the token (encrypted) to a database table and supports automatic refresh [[1]](https://github.com/apache/superset/pull/38469): ```python OAUTH_PROVIDERS = [ { "name": "zitadel", "save_token": True, # enables token persistence "remote_app": { "client_id": "...", "client_secret": "...", "client_kwargs": { "scope": "openid profile email offline_access" # include offline_access for refresh tokens }, }, } ] ``` **Until that feature is merged**, the pragmatic approach is to write a **custom security manager** that overrides the OAuth callback to capture and store the token yourself. For example: ```python from superset.security import SupersetSecurityManager from flask import session class CustomSecurityManager(SupersetSecurityManager): def oauth_user_info(self, provider, response=None): # The token is available in the FAB session during this callback # You can store it in your own table or in Flask session if provider == "zitadel": token = response # contains access_token, refresh_token, etc. # Store token for later use (e.g., in a custom DB table) session["zitadel_token"] = token return super().oauth_user_info(provider, response) ``` Then configure `CUSTOM_SECURITY_MANAGER = CustomSecurityManager` in `superset_config.py`. **Why Superset doesn't persist external tokens by default**: It's a design choice — Superset treats OAuth purely as an authentication mechanism (identity verification), not as a token broker. Persisting external tokens introduces security responsibility (encryption, refresh handling, token revocation) that isn't needed for Superset's core use case of visualizing data. **Summary of recommendations for your use case:** - Watch/use PR #38469 if it gets merged — it solves exactly your problem - In the meantime, implement a custom security manager to capture and store the Zitadel token at login time - Request `offline_access` scope from Zitadel to get a refresh token, and implement your own refresh logic for when the access token expires - Store tokens server-side (encrypted in a database table), not in the browser session cookie <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=reply-with-mention&utm_term=apache%2Fsuperset).* --- Docs are dead. Just use [Dosu](https://dosu.dev?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-tagline&utm_term=apache%2Fsuperset). [](https://app.dosu.dev/response-feedback?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-feedback&utm_term=apache%2Fsuperset&message_id=11389675-cf59-43f1-9902-07026a6c0c4b) [](https://github.dosu.com/apache/superset?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-ask-repo&utm_term=apache%2Fsuperset) [](https://app.dosu.dev/signup?referrer=openSource&source=github-footer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-share-team&utm_term=apache%2Fsuperset) GitHub link: https://github.com/apache/superset/discussions/40283#discussioncomment-16986638 ---- 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]
