[GH-ISSUE #24618] bug: MCP OAuth sessions wiped after every chat completion (get_system_oauth_token fallback) #107355

Open
opened 2026-05-18 06:09:19 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @verdier on GitHub (May 12, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/24618

Bug

When a user has SSO login (e.g. Microsoft Entra) and at least one MCP server with auth_type: oauth_2.1, the MCP OAuth session is deleted from the database at every chat completion. The next tool invocation then fails with 401.

Steps to reproduce

  1. Configure SSO (Microsoft / Google / OIDC).
  2. Add an MCP tool server using OAuth 2.1, e.g. Coda — https://coda.io/apis/mcp.
  3. Authorize it as a user. Confirm an oauth_session row is created with provider='mcp:<server_id>'.
  4. Send any chat message (with or without the MCP tool actually selected).
  5. The MCP oauth_session row is gone. Subsequent tool calls return 401 Unauthorized.

Root cause

backend/open_webui/utils/middleware.py::get_system_oauth_token() is called on every chat completion (via the __oauth_token__ context value). When no oauth_session_id cookie is present, it falls back to the most recent OAuth session of the user, regardless of provider:

sessions = await OAuthSessions.get_sessions_by_user_id(user.id)
if sessions:
    best = max(sessions, key=lambda s: s.updated_at)
    oauth_token = await request.app.state.oauth_manager.get_oauth_token(
        user.id, best.id,
    )

When best is an MCP session (e.g. mcp:coda), it gets handed to the SSO oauth_manager, which doesn't know any mcp:* provider. _perform_token_refresh then logs:

ERROR | _perform_token_refresh:1155 - No OAuth client found for provider mcp:coda
WARNING | get_oauth_token:1096 - Token refresh failed for user ..., provider mcp:coda, deleting session ...

…and the session is deleted (OAuthSessions.delete_session_by_id). The MCP oauth_client_manager (which does know how to refresh mcp:* tokens) is never consulted in this code path.

Suggested fix

Skip MCP-provider sessions in the SSO fallback — MCP token refresh is already handled separately by oauth_client_manager.get_oauth_token() in process_chat_payload:

sessions = await OAuthSessions.get_sessions_by_user_id(user.id)
sessions = [s for s in sessions if not (s.provider or '').startswith('mcp:')]
if sessions:
    best = max(sessions, key=lambda s: s.updated_at)
    ...

Happy to send a PR if useful.

Version

OpenWebUI 0.9.5 (ghcr.io/open-webui/open-webui:latest on 2026-05-12).

Originally created by @verdier on GitHub (May 12, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/24618 ### Bug When a user has SSO login (e.g. Microsoft Entra) **and** at least one MCP server with `auth_type: oauth_2.1`, the MCP OAuth session is deleted from the database at every chat completion. The next tool invocation then fails with 401. ### Steps to reproduce 1. Configure SSO (Microsoft / Google / OIDC). 2. Add an MCP tool server using OAuth 2.1, e.g. Coda — `https://coda.io/apis/mcp`. 3. Authorize it as a user. Confirm an `oauth_session` row is created with `provider='mcp:<server_id>'`. 4. Send any chat message (with or without the MCP tool actually selected). 5. The MCP `oauth_session` row is gone. Subsequent tool calls return `401 Unauthorized`. ### Root cause `backend/open_webui/utils/middleware.py::get_system_oauth_token()` is called on every chat completion (via the `__oauth_token__` context value). When no `oauth_session_id` cookie is present, it falls back to **the most recent OAuth session of the user, regardless of provider**: ```python sessions = await OAuthSessions.get_sessions_by_user_id(user.id) if sessions: best = max(sessions, key=lambda s: s.updated_at) oauth_token = await request.app.state.oauth_manager.get_oauth_token( user.id, best.id, ) ``` When `best` is an MCP session (e.g. `mcp:coda`), it gets handed to the SSO `oauth_manager`, which doesn't know any `mcp:*` provider. `_perform_token_refresh` then logs: ``` ERROR | _perform_token_refresh:1155 - No OAuth client found for provider mcp:coda WARNING | get_oauth_token:1096 - Token refresh failed for user ..., provider mcp:coda, deleting session ... ``` …and the session is deleted (`OAuthSessions.delete_session_by_id`). The MCP `oauth_client_manager` (which *does* know how to refresh `mcp:*` tokens) is never consulted in this code path. ### Suggested fix Skip MCP-provider sessions in the SSO fallback — MCP token refresh is already handled separately by `oauth_client_manager.get_oauth_token()` in `process_chat_payload`: ```python sessions = await OAuthSessions.get_sessions_by_user_id(user.id) sessions = [s for s in sessions if not (s.provider or '').startswith('mcp:')] if sessions: best = max(sessions, key=lambda s: s.updated_at) ... ``` Happy to send a PR if useful. ### Version OpenWebUI 0.9.5 (`ghcr.io/open-webui/open-webui:latest` on 2026-05-12).
Author
Owner

@owui-terminator[bot] commented on GitHub (May 12, 2026):

⚠️ Missing Issue Title Prefix

@verdier, your issue title is missing a categorising prefix (e.g. bug:, feat:, docs:).

Please update the title to lead with one of:

  • bug: bug report or error
  • feat: feature request or enhancement
  • docs: documentation issue
  • question: usage question
  • help: support request

Example: bug: Login fails when the password contains special characters

<!-- gh-comment-id:4430962998 --> @owui-terminator[bot] commented on GitHub (May 12, 2026): # ⚠️ Missing Issue Title Prefix @verdier, your issue title is missing a categorising prefix (e.g. `bug:`, `feat:`, `docs:`). Please update the title to lead with one of: - **bug**: bug report or error - **feat**: feature request or enhancement - **docs**: documentation issue - **question**: usage question - **help**: support request Example: `bug: Login fails when the password contains special characters`
Author
Owner

@owui-terminator[bot] commented on GitHub (May 12, 2026):

🔍 Related Issues Found

I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions:

  1. 🟣 #24039 feat: Allow Clearing of Oauth Sessions for MCP Connections
    This feature request is directly about managing/deleting MCP OAuth sessions. It confirms MCP sessions are stored in oauth_sessions, which is the same table being incorrectly deleted in the new bug.
    by anengineerdude

  2. 🟣 #20291 issue: MCP Atlassian OAuth token refresh fails with "Constructor parameter should be str" in v0.6.43
    This bug is also about MCP OAuth token refresh failing and the session being deleted after refresh attempts. While the error differs, it is closely related because both involve MCP OAuth sessions being removed when refresh logic misroutes.
    by rolandscho · bug

  3. 🟢 #24615 issue: Older OAuth session deletion not being reflected in the frontend when OAUTH_MAX_SESSIONS_PER_USER is set to 1
    This is about OAuth session deletion behavior when the max-session limit is enforced. It is not the same root cause, but it is adjacent because it deals with automatic deletion of OAuth sessions and the resulting session-state mismatch.
    by shubhankar-ncp · bug


💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead.

This comment was generated automatically. React with 👍 if helpful, 👎 if not.

<!-- gh-comment-id:4430964209 --> @owui-terminator[bot] commented on GitHub (May 12, 2026): <!-- terminator-bot:related-issues-reply --> 🔍 **Related Issues Found** I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions: 1. 🟣 [#24039](https://github.com/open-webui/open-webui/issues/24039) **feat: Allow Clearing of Oauth Sessions for MCP Connections** *This feature request is directly about managing/deleting MCP OAuth sessions. It confirms MCP sessions are stored in `oauth_sessions`, which is the same table being incorrectly deleted in the new bug.* *by anengineerdude* 2. 🟣 [#20291](https://github.com/open-webui/open-webui/issues/20291) **issue: MCP Atlassian OAuth token refresh fails with "Constructor parameter should be str" in v0.6.43** *This bug is also about MCP OAuth token refresh failing and the session being deleted after refresh attempts. While the error differs, it is closely related because both involve MCP OAuth sessions being removed when refresh logic misroutes.* *by rolandscho · `bug`* 3. 🟢 [#24615](https://github.com/open-webui/open-webui/issues/24615) **issue: Older OAuth session deletion not being reflected in the frontend when OAUTH_MAX_SESSIONS_PER_USER is set to 1** *This is about OAuth session deletion behavior when the max-session limit is enforced. It is not the same root cause, but it is adjacent because it deals with automatic deletion of OAuth sessions and the resulting session-state mismatch.* *by shubhankar-ncp · `bug`* --- 💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead. *This comment was generated automatically.* React with 👍 if helpful, 👎 if not.
Author
Owner

@los93sol commented on GitHub (May 13, 2026):

Ran into the same issue and applied the fix mentioned, worked perfectly for me

<!-- gh-comment-id:4441370465 --> @los93sol commented on GitHub (May 13, 2026): Ran into the same issue and applied the fix mentioned, worked perfectly for me
Author
Owner

@IVVI0927 commented on GitHub (May 17, 2026):

Hi @verdier, thanks for the detailed root-cause analysis and the suggested fix.

My plan is to apply your suggested filter in get_system_oauth_token() in backend/open_webui/utils/middleware.py — skipping sessions whose provider starts with mcp: so they aren't passed to the SSO oauth_manager and incorrectly deleted.

Will submit a PR shortly against the dev branch. Happy to adjust based on feedback.

<!-- gh-comment-id:4469258260 --> @IVVI0927 commented on GitHub (May 17, 2026): Hi @verdier, thanks for the detailed root-cause analysis and the suggested fix. My plan is to apply your suggested filter in `get_system_oauth_token()` in `backend/open_webui/utils/middleware.py` — skipping sessions whose provider starts with `mcp:` so they aren't passed to the SSO oauth_manager and incorrectly deleted. Will submit a PR shortly against the `dev` branch. Happy to adjust based on feedback.
Author
Owner

@IVVI0927 commented on GitHub (May 17, 2026):

Hi @Sean-Kenneth-Doherty, thanks for the regression-test target — adopted it.

Quick note on test strategy: since importing middleware.py pulls in the full DB/config initialization, my test file inlines the filter logic (with a # keep in sync with middleware.py comment) rather than importing get_system_oauth_token directly.

Trade-off: future edits to the real function won't automatically propagate to the test, but it keeps the test fast and avoids touching test infrastructure outside the scope of this fix. Happy to switch to a fixture-based approach if maintainers prefer.

The test covers:

  • SSO + MCP coexistence → SSO is selected (your regression target)
  • MCP-only sessions → SSO oauth_manager not called
  • SSO-only sessions → unchanged behaviour
  • provider=None sessions → preserved (covers the (s.provider or '') guard)
  • Cookie path → unaffected by the filter
<!-- gh-comment-id:4469344980 --> @IVVI0927 commented on GitHub (May 17, 2026): Hi @Sean-Kenneth-Doherty, thanks for the regression-test target — adopted it. Quick note on test strategy: since importing `middleware.py` pulls in the full DB/config initialization, my test file inlines the filter logic (with a `# keep in sync with middleware.py` comment) rather than importing `get_system_oauth_token` directly. Trade-off: future edits to the real function won't automatically propagate to the test, but it keeps the test fast and avoids touching test infrastructure outside the scope of this fix. Happy to switch to a fixture-based approach if maintainers prefer. The test covers: - SSO + MCP coexistence → SSO is selected (your regression target) - MCP-only sessions → SSO `oauth_manager` not called - SSO-only sessions → unchanged behaviour - `provider=None` sessions → preserved (covers the `(s.provider or '')` guard) - Cookie path → unaffected by the filter
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#107355