anthropics / anthropics/claude-ai-mcp
MCP custom connector authenticates with client_secret_post, ignores the authorization server's advertised token_endpoint_auth_methods_supported, and does not fall back to client_secret_basic.
- 主要言語
- 言語のデータがありません
- スター
- 471
- フォーク
- 76
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
### MCP server URL
https://mcpdemo.loretz.pw
### 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-07-22 07:31 UTC
### Browser and OS
Chrome 138 on Windows 11
### Describe the issue
When a Claude.ai custom remote MCP connector is configured as a confidential client
(client_id + client_secret in Advanced settings), Claude authenticates to the OAuth token
endpoint using client_secret_post (credentials in the request body). It does this even when
the authorization server's metadata advertises client_secret_basic as the ONLY supported
method, and it does not fall back to client_secret_basic when the endpoint rejects the
request. As a result, any RFC-compliant authorization server that requires HTTP Basic
(client_secret_basic) — a common, standards-compliant, FAPI-recommended posture — cannot be
connected. In our case the upstream provider (Charles Schwab's OAuth token endpoint) accepts
only client_secret_basic, so a direct connection fails at the token exchange with
invalid_client.
### Issue details
```shell
The connection fails at the OAuth token exchange (POST to the token endpoint) with an
invalid_client error from the endpoint. In Claude.ai the user sees a pop-up:
"Authorization with failed. You can check your credentials and
permissions. If this persists, share this reference with support: ofid_77cd3db35c80a4ce"
Error / reference IDs: ofid_77cd3db35c80a4ce, ofid_5e3aa9fde750c2b9
Root cause (proven end-to-end):
1. The token endpoint requires client_secret_basic (HTTP Basic) and rejects
client_secret_post with invalid_client. Verified by direct probe: a Basic-auth token
request returns invalid_grant (auth accepted, only the dummy code rejected), while a
client_secret_post request returns invalid_client (auth rejected).
2. Claude sends client_secret_post. Captured token request has no Authorization header and
carries client_secret in the form body.
3. Claude ignores the advertised auth method. We changed the authorization-server metadata
to advertise ONLY ["client_secret_basic"]. Claude fetched that metadata fresh 48 seconds
before the token exchange (confirmed via server logs — not a caching artifact) and still
authenticated with client_secret_post.
4. Claude does not fall back to Basic. With the endpoint returning 401 invalid_client plus
WWW-Authenticate: Basic (and the authorization code left intact so a Basic retry could
succeed), Claude did not retry with Basic — it failed the connection.
This is reproducible against a minimal MCP server (no Schwab required): advertise
"token_endpoint_auth_methods_supported": ["client_secret_basic"] and reject client_secret_post.
```
### Expected behavior
Per RFC 6749 §2.3.1 and RFC 8414, the client should authenticate using a client
authentication method that the authorization server advertises in
token_endpoint_auth_methods_supported. When the server advertises client_secret_basic
(HTTP Basic) as the only method, Claude should use client_secret_basic.
At minimum, on receiving 401 invalid_client, Claude should retry with an advertised method
(client_secret_basic) before failing the connection.
Note: the MCP authorization spec frames clients as public clients
(token_endpoint_auth_method: "none" + PKCE). This report concerns the confidential-client
path that the custom-connector Advanced settings explicitly enable (client_id + secret);
on that path the advertised authentication method should be honored.
### Logs from your server
```shell
# Authorization-server metadata we served (verified via curl) — advertises Basic only:
token_endpoint_auth_methods_supported: ["client_secret_basic"]
# Claude fetched that metadata FRESH, 48s before the token exchange (not cached):
2026-07-22 07:10:02 UTC GET /.well-known/oauth-authorization-server 200
2026-07-22 07:10:03 UTC GET /authorize 302
2026-07-22 07:10:50 UTC POST /token <- see body below
# Claude's POST /token — NO Authorization header; client_secret in the BODY (client_secret_post):
POST /token
User-Agent: python-httpx/0.28.1
Content-Type: application/x-www-form-urlencoded
X-Real-Ip: 160.79.106.34 (Anthropic egress range 160.79.104.0/21)
(no Authorization header)
body: grant_type=authorization_code&code=…&client_id=…&code_verifier=…
&redirect_uri=https://claude.ai/api/mcp/auth_callback
&resource=https://mcpdemo.loretz.pw/mcp
&client_secret=…
# When the endpoint rejects client_secret_post like Schwab does, Claude does NOT retry with Basic:
2026-07-22 07:31:44 UTC POST /token -> 401 invalid_client (WWW-Authenticate: Basic), code left intact
(no subsequent /token with HTTP Basic — connection failed)
# For contrast, direct probe of the Schwab token endpoint (dummy code):
# HTTP Basic -> invalid_grant (auth accepted, code rejected)
# client_secret_post -> invalid_client (auth rejected)
```
### Additional context
- OAuth provider / upstream: Charles Schwab Trader API OAuth
(token endpoint https://api.schwabapi.com/v1/oauth/token) — accepts client_secret_basic only.
- Client authentication is the sole cause. Ruled out: PKCE (endpoint handles it),
RFC 8707 resource indicator, redirect_uri switching (consistent claude.ai; both
claude.ai and claude.com callbacks are whitelisted upstream), redirect_uri validation
at /authorize (upstream is permissive there), and source IP (Anthropic backend reaches
the endpoint fine from 160.79.106.34).
- Minimal reproduction (no upstream provider needed): stand up an MCP server that
advertises "token_endpoint_auth_methods_supported": ["client_secret_basic"] and returns
401 invalid_client for client_secret_post. Claude will authenticate with
client_secret_post and fail without retrying Basic.
- Requested fix (either): (1) honor token_endpoint_auth_methods_supported and use
client_secret_basic when advertised; or (2) fall back to client_secret_basic on
invalid_client.
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
評価
この issue はまだ評価されていません。