Skip to content

Custom Connector OAuth fails with ofid_c2b33f0682e60e9a after successful WorkOS authorization (302 with code issued correctly) #271

Description

@brunoprados93

MCP server URL

https://inco-bot-dashboard-production.up.railway.app/mcp/v1

Where does the issue occur?

When auth finishes and redirects back to Claude.ai

Transport used

streamable-http

Client registration type

Static

SSE only: Does your server return the expected status code for POST requests?

Not applicable (my server does not use SSE)

When did you last reproduce this?

2026-05-08, ~16:30 BRT (UTC-3)

Browser and OS

Chrome on Windows 11

Describe the issue

When connecting a self-hosted MCP server as a custom connector in claude.ai (Team workspace), the OAuth 2.1 Authorization Code Flow with WorkOS AuthKit as the authorization server completes successfully through the authorize step. WorkOS returns a 302 redirect with a valid code parameter to the claude.ai callback. However, claude.ai then displays:

"Authorization with the MCP server failed. You can check your credentials and permissions. If this persists, share this reference with support: ofid_c2b33f0682e60e9a"

The MCP server's /token endpoint is never called — confirmed by absence of any POST requests in server logs after the authorize redirect. The failure happens entirely on the claude.ai side, between receiving the authorization code and the token exchange step.

This appears to be the same family of issues as #155, #164, #171, #184, #215, #217, where OAuth completes at the authorization server but claude.ai fails to finalize the connector authorization.

Issue details

MCP server URL: https://inco-bot-dashboard-production.up.railway.app/mcp/v1
Reference ID: ofid_c2b33f0682e60e9a

Authorization server: WorkOS AuthKit (persuasive-balloon-82-staging.authkit.app)
Client ID: client_01KR250ERD57Z6MR81V0DCNP74
Application type: Confidential client (OAuth, manually pre-registered)
Methods enabled: Email + Password
Custom scopes declared in WorkOS: read:all, read:health
Default scopes claude.ai requests: read:all, read:health, offline_access
Redirect URIs registered: https://claude.ai/api/mcp/auth_callback (default), https://claude.com/api/mcp/auth_callback
Audience (resource indicator): https://inco-bot-dashboard-production.up.railway.app/mcp/v1
PKCE: enabled (S256)

Steps to reproduce:
1. Configure WorkOS Application as confidential OAuth client with Authorization Code Flow + PKCE
2. Register both claude.ai and claude.com callback URLs as Redirect URIs
3. Define custom scopes "read:all" and "read:health" matching what the MCP server declares
4. In claude.ai, go to Settings → Connectors → Add custom connector → enter MCP server URL
5. Click "Connect"
6. Authenticate at WorkOS AuthKit (Email + Password)
7. Approve consent screen
8. Failure: redirect back to claude.ai shows the error UI with ofid_* reference

Sequence of distinct errors observed during debugging:

Phase 1 (custom scopes not yet declared in WorkOS):
- Error displayed: "code: Field required"
- Root cause: WorkOS returned ?error=invalid_scope on the callback URL, but claude.ai parsed it as a missing "code" parameter (same pattern documented in #122 and discussion #588)
- Workaround: declared the scopes in WorkOS, this error stopped

Phase 2 (custom scopes correctly declared):
- Error displayed: ofid_c2b33f0682e60e9a
- This is the issue being reported here

DevTools Network capture of the 302 from WorkOS authorize endpoint shows the redirect Location is https://claude.ai/api/mcp/auth_callback?code=<valid_code>&state=<state> — the code parameter is present, meaning the authorize step succeeded.

Expected behavior

After the successful authorization at the WorkOS AuthKit, claude.ai should:

  1. Receive the 302 redirect with the authorization code
  2. Discover the token endpoint via /.well-known/oauth-authorization-server (or use the metadata it already obtained)
  3. POST to the token endpoint with code + PKCE verifier to exchange for an access token
  4. Store the access token
  5. Call the MCP server with Authorization: Bearer <access_token> header
  6. Mark the connector as Connected and expose available tools

Instead, none of steps 2 through 6 occur. There is no POST to the token endpoint at any point — confirmed by server-side logs.

Logs from your server

Server-side observations during a failed connection attempt:

Pre-authorization phase:
- Three POST /mcp probes received from User-Agent "Claude-User", all unauthenticated, ~2 seconds apart
- Each returned 401 with WWW-Authenticate: Bearer resource_metadata="https://inco-bot-dashboard-production.up.railway.app/.well-known/oauth-protected-resource"
- All three responses are spec-compliant per RFC 6750

Discovery phase:
- GET /.well-known/oauth-protected-resource — returned 200 with valid metadata
- GET /.well-known/oauth-authorization-server — returned 200 with valid metadata pointing to the WorkOS AuthKit endpoints

Authorization phase:
- WorkOS authorize endpoint received and processed the request correctly (verified via DevTools Network tab)
- WorkOS issued a 302 with a valid code parameter to the claude.ai callback (also verified)

Post-authorization phase:
- NO POST /token request ever reached the MCP server
- NO authenticated POST /mcp request ever reached the MCP server
- claude.ai displayed the ofid_* error in the UI

The complete absence of any further requests to the MCP server after the 302 indicates the failure is entirely on the claude.ai side, before it attempts the token exchange.

Additional context

What works (rules out MCP server implementation)

The same MCP server connects and works correctly via:

  1. Claude Code CLIclaude mcp add --transport http <URL> with a static Bearer token completes successfully and tools function as expected
  2. Direct API callscurl -H "Authorization: Bearer <token>" <URL>/list_tools returns the 7 expected tools
  3. MCP Inspector

This rules out the MCP server implementation, the discovery endpoints, and the WorkOS configuration as the failing component. The failure is exclusively in the claude.ai web "Add custom connector" path, post-authorization.

Related issues showing the same family of failure mode

Context

This MCP server is part of an internal observability dashboard for a Brazilian fintech. The custom connector path is required because the data is internal and cannot be hosted as a publicly listed connector.

Happy to provide additional logs, full DevTools HAR captures, or test fix candidates if you reach out.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions