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).

[![Leave 
Feedback](https://img.shields.io/badge/Leave%20Feedback-555555?style=flat)](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)
 [![Ask Dosu about 
superset](https://img.shields.io/badge/Ask%20Dosu%20about%20superset-2f7b3f?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iODYiIGhlaWdodD0iODkiIHZpZXdCb3g9IjAgMCA4NiA4OSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNS4yOTIzNiAxMi43OTI4TDE3Ljc1OTMgNi42ODE4OFY3Mi41NjY3TDUuMjkyMzYgODQuMDYxOFYxMi43OTI4WiIgZmlsbD0iI0I0QkI5MSIvPjxwYXRoIGQ9Ik0xOC4yNTc1IDczLjExOTZMNTkuMTMyOSA3Mi43NDhMNTEuNzAxMSA4Mi40MDk1TDI5LjAzMzggODYuMjkxTDYuMjM5NjIgODUuMTU1NEwxOC4yNTc1IDczLjExOTZaIiBmaWxsPSIjNzc4NTYxIi8%2BPHBhdGggZD0iTTE3LjQ5MTYgMy43MzYzM0wzLjU4NTU3IDEyLjcwOTlWODMuNTc5MkMzLjU4NTU3IDg0Ljc1NDIgNC45ODU2MyA4NS4zNjUyIDUuODQ3MDUg
 
ODQuNTY2TDE5LjYyOTYgNzEuNzgwMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSI2LjQyODQ0IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48bWFzayBpZD0iZG9zdS1kLWN1dG91dCIgZmlsbD0id2hpdGUiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNDAuNzA0IDAuNTE4MDY2SDE3LjA0MzlWNzYuMjIyMUg0MC43MDRINDIuNTgwNUg0Ny44MDEzQzY4LjcwNjQgNzYuMjIyMSA4NS42NTMzIDU5LjI3NTIgODUuNjUzMyAzOC4zNzAxQzg1LjY1MzMgMTcuNDY1IDY4LjcwNjMgMC41MTgwNjYgNDcuODAxMyAwLjUxODA2Nkg0Mi41ODA1SDQwLjcwNFoiLz48L21hc2s%2BPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00MC43MDQgMC41MTgwNjZIMTcuMDQzOVY3Ni4yMjIxSDQwLjcwNEg0Mi41ODA1SDQ3LjgwMTNDNjguNzA2NCA3Ni4yMjIxIDg1LjY1MzMgNTkuMjc1MiA4NS42NTMzIDM4LjM3MDFDODUuNjUzMyAxNy40NjUgNjguNzA2MyAwLjUxODA2NiA0Ny44MDEzIDAuNTE4MDY2SDQyLjU4MDVINDAuNzA0WiIgZmlsbD0iI0YzRjZGMSIvPjxwYXRoIGQ9Ik0xNy4wNDM5IDAuNTE4MDY2Vi02LjU3OTE5SDkuOTQ2NjlWMC41MTgwNjZIMTcuMDQzOVpNMTcuMDQzOSA3Ni4yMjIxSDkuOTQ2NjlWODMuMzE5NEgxNy4wNDM5Vjc2LjIyMjFaTTE3LjA0MzkgNy42MTUzMkg0MC43MDRWLTYuNTc5MTlIMTcuMDQzOVY3LjYxNTMyWk0
 
yNC4xNDEyIDc2LjIyMjFWMC41MTgwNjZIOS45NDY2OVY3Ni4yMjIxSDI0LjE0MTJaTTQwLjcwNCA2OS4xMjQ5SDE3LjA0MzlWODMuMzE5NEg0MC43MDRWNjkuMTI0OVpNNDIuNTgwNSA2OS4xMjQ5SDQwLjcwNFY4My4zMTk0SDQyLjU4MDVWNjkuMTI0OVpNNDcuODAxMyA2OS4xMjQ5SDQyLjU4MDVWODMuMzE5NEg0Ny44MDEzVjY5LjEyNDlaTTc4LjU1NiAzOC4zNzAxQzc4LjU1NiA1NS4zNTU1IDY0Ljc4NjcgNjkuMTI0OSA0Ny44MDEzIDY5LjEyNDlWODMuMzE5NEM3Mi42MjYxIDgzLjMxOTQgOTIuNzUwNSA2My4xOTQ5IDkyLjc1MDUgMzguMzcwMUg3OC41NTZaTTQ3LjgwMTMgNy42MTUzMkM2NC43ODY2IDcuNjE1MzIgNzguNTU2IDIxLjM4NDcgNzguNTU2IDM4LjM3MDFIOTIuNzUwNUM5Mi43NTA1IDEzLjU0NTMgNzIuNjI2IC02LjU3OTE5IDQ3LjgwMTMgLTYuNTc5MTlWNy42MTUzMlpNNDIuNTgwNSA3LjYxNTMySDQ3LjgwMTNWLTYuNTc5MTlINDIuNTgwNVY3LjYxNTMyWk00MC43MDQgNy42MTUzMkg0Mi41ODA1Vi02LjU3OTE5SDQwLjcwNFY3LjYxNTMyWiIgZmlsbD0iYmxhY2siIG1hc2s9InVybCgjZG9zdS1kLWN1dG91dCkiLz48cGF0aCBkPSJNNjguOTIxNSAzNi4wMTM1QzY4LjkyMTUgMzYuMDEzNSA2NS43MzY5IDQ5LjQ3MzggNTEuNDIzMSA0OS40NzM4QzM3LjEwOTMgNDkuNDczOCAzMi41Nzg3IDM3LjM1OTYgMzIuNTc4NyAzNi4wMTM1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjcuNjkxNjEi
 
IHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0wLjM0ODYzMyA4NS40OTQ2QzAuMzQ4NjMzIDg1LjQ5NDYgMjkuNDg1NiA4NS44MzA5IDM0LjgwOSA4NS42OThDNDQuODMzNyA4NS40NDc3IDUxLjI4NzIgODQuNDAyIDU3LjUyNjkgNzguOTcyNEM2Mi44MTI5IDc0LjM3MjcgNzUuMTM0MiA1OS42ODM2IDc1LjEzNDIgNTkuNjgzNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSI2LjE2NDgyIi8%2BPC9zdmc%2B)](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)
 [![Share Dosu with your 
team](https://img.shields.io/badge/Share%20Dosu%20with%20your%20team-1f6feb?style=flat)](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]

Reply via email to