diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index fa6e1bddb3..c5f9f01803 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -3042,6 +3042,10 @@ async def get_system_oauth_token(request, user): from open_webui.models.oauth_sessions import OAuthSessions sessions = await OAuthSessions.get_sessions_by_user_id(user.id) + # Filter out MCP-provider sessions — their token refresh is handled + # separately by oauth_client_manager. Passing them to the SSO + # oauth_manager causes a failed refresh and session deletion (#24618). + sessions = [s for s in sessions if not (s.provider or '').startswith('mcp:')] if sessions: best = max(sessions, key=lambda s: s.updated_at) oauth_token = await request.app.state.oauth_manager.get_oauth_token( diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index 17725959ee..13cfc43de8 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -1077,6 +1077,18 @@ class OAuthManager: log.warning(f'No OAuth session found for user {user_id}, session {session_id}') return None + # Guard: MCP-provider sessions must be refreshed by + # oauth_client_manager, not the SSO OAuthManager. If one + # reaches here (e.g. via a stale cookie), bail out early + # instead of attempting a refresh that will fail and delete + # the session (#24618). + if (session.provider or '').startswith('mcp:'): + log.debug( + f'Skipping MCP session {session.id} (provider={session.provider}) ' + f'in SSO OAuthManager — handled by oauth_client_manager' + ) + return None + if ( force_refresh or session.expires_at is None