Claude.ai never calls /oauth2/authorize after successful dynamic client registration

Resolved 💬 2 comments Opened Mar 3, 2026 by subsetpark Closed Mar 6, 2026

Summary

Claude.ai fails to complete the OAuth authorization_code flow for our custom MCP server. Dynamic client registration succeeds, but Claude.ai never redirects to the authorize endpoint — it loops back to the MCP endpoint without a token.

Claude Code CLI works perfectly on the same server.

Related to #11814 (locked).

Server

  • URL: https://app.flowgladpay.com/api/mcp
  • Stack: Next.js 16 + Better Auth oauthProvider plugin, ECS Fargate behind ALB
  • OAuth: RFC 8414/9728 compliant, DCR enabled, PKCE (S256), public clients supported

Observed behavior (from structured OTLP logs)

Claude.ai (python-httpx/0.28.1):

  1. POST /api/mcp → 401 with WWW-Authenticate: Bearer resource_metadata=".../.well-known/oauth-protected-resource"
  2. Fetches protected resource metadata ✅
  3. Fetches AS metadata (/.well-known/oauth-authorization-server) ✅
  4. POST /api/auth/oauth2/register → 200, returns valid client_id, redirect_uris: ["https://claude.ai/api/mcp/auth_callback"], grant_types: ["authorization_code", "refresh_token"]
  5. GET /oauth2/authorize is never called
  6. Immediately retries POST /api/mcp without a token → 401
  7. Repeats steps 1–6 in a loop

Expected behavior

After step 4, Claude.ai should construct an authorize URL and open a browser popup for user login/consent, then exchange the auth code for a token via /oauth2/token.

Claude Code works

The same server works with Claude Code CLI (claude-code/2.1.63):

register → authorize (browser) → token exchange → MCP authenticated ✅

Registration response (verified manually)

{
  "client_id": "unWlXcgouKGcfBQjDAYRJCsxLsHEiETa",
  "scope": "jobs:read jobs:write credentials:read offline_access",
  "client_name": "Claude",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "public": true
}

AS metadata (verified)

{
  "issuer": "https://app.flowgladpay.com/api/auth",
  "authorization_endpoint": "https://app.flowgladpay.com/api/auth/oauth2/authorize",
  "token_endpoint": "https://app.flowgladpay.com/api/auth/oauth2/token",
  "registration_endpoint": "https://app.flowgladpay.com/api/auth/oauth2/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"],
  "code_challenge_methods_supported": ["S256"]
}

Environment

  • Claude.ai web (not Desktop, not CLI)
  • User-Agent: python-httpx/0.28.1
  • Date: 2026-03-03

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗