Skip to content

[Bug]: MCP OAuth reauthorization prematurely closes popup on first poll tick and rejects completion with 409 (stale "authorized" status in oauth_configs) #6477

Description

@Xytronix

Prerequisites

  • I have searched existing issues and discussions to avoid duplicates
  • I am using the latest version (or have tested against main/nightly)

Description

When re-authorizing an existing OAuth-based MCP client (auth_type='oauth' or per_user_oauth), the frontend <OAuth2Authorizer /> prematurely closes the browser authorization popup on the very first polling tick (~2s) and fires complete-oauth. The backend rejects complete-oauth with HTTP 409 Conflict because the in-flight authorization flow is still pending, but the UI misinterprets the 409 as a successful race condition and shows a false "Success" toast.

As a result:

  1. The user's authorization popup is closed before they can approve consent at the upstream IdP.
  2. No authorization code is exchanged, and the expired/revoked OAuth token is never updated.
  3. The MCP client remains disconnected in needs_reauth status despite the UI indicating success.

Root Cause

  1. Stale status polling in getOAuthConfigStatus:
    GET /api/oauth/config/{id}/status (transports/bifrost-http/handlers/mcpoauth2.go:175) reads oauth_configs.status. For an existing client that was authorized in the past, oauth_configs.status is permanently "authorized" (it never regresses to "pending" during reauth).
  2. OAuth2Authorizer.tsx polling interval:
    startPolling in ui/app/workspace/mcp-registry/views/oauth2Authorizer.tsx:49-65 polls getOAuthStatus(oauthConfigId) every 2 seconds. On the first tick, it receives status: "authorized" from oauth_configs. It immediately calls popupRef.current.close() and triggers handleOAuthComplete().
  3. Backend correctly detects premature completion:
    completeMCPClientOAuth (transports/bifrost-http/handlers/mcp.go:3321) checks isPrematureOAuthCompletion(pendingFlow, time.Now()). Because the reauth flow in mcp_oauth_flows is still in status "pending", it returns 409 Conflict: "Authorization has not completed yet: the browser flow may still be open...".
  4. UI false success masking:
    onConflict in ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx:1178-1193 catches the 409 error, treats it as "flow completion raced / double submit", and shows a green success toast while dismissing the modal.

Steps to reproduce

  1. Configure an MCP client using OAuth authentication (e.g. Notion or any OAuth server) and complete initial setup.
  2. Invalidate or let the credential expire so the client transitions to needs_reauth.
  3. Click Re-authenticate in the MCP registry table.
  4. Click Continue in the confirmation dialog to open the OAuth popup window.
  5. Wait 2 seconds without interacting with the popup.
  6. Observe that the popup window automatically closes and the UI shows a green success toast ("MCP client re-authorized successfully"), while the client remains in needs_reauth and cannot connect.

Expected behavior

The status endpoint should reflect the active mcp_oauth_flows state (or the authorizer should poll the specific flow / await the oauth_success postMessage callback from the popup before completing), and the popup should remain open until authentication is completed by the user.

Actual behavior

The popup closes after 2 seconds, complete-oauth returns 409, the UI displays a false success toast, and tokens are never refreshed.

Affected area(s)

  • Transports (HTTP)
  • UI (React)
  • Framework

Version

dev @ 9dd8cfa16318433bd409c52c891caec551815dca (2026-08-24)

Severity

High (major functionality broken)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions