anthropics / anthropics/claude-ai-mcp

AWS API Gateway silently renames WWW-Authenticate header, breaking MCP OAuth resource-metadata discovery

Abierto
#748 0 comentarios 4 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Sin datos de lenguaje
Estrellas
471
Forks
76
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

### MCP server URL

(AWS API Gateway + Lambda, private — happy to share a reproduction endpoint privately if useful)

### Where does the issue occur?

When pressing the Connect button

### Transport used

streamable-http

### Client registration type

Dynamic (Cognito-backed OAuth 2.1: PKCE S256, RFC 8414 Authorization Server Metadata, RFC 9728 Protected Resource Metadata all served correctly)

### Describe the issue

Our 401 response includes a `WWW-Authenticate: Bearer realm="...", resource_metadata="https://.../.well-known/oauth-protected-resource"` header. We confirmed by direct `curl` that this URL serves valid RFC 9728 metadata pointing at an authorization server metadata document that itself resolves correctly. We also confirmed, by hand-navigating the exact `authorize` URL Claude's connector generated (same client_id, code_challenge, redirect_uri), that it lands cleanly on our IdP's real sign-in page — so whatever a correctly-discovering client would have been sent to does work.

Root cause found: our server sits behind AWS API Gateway (Lambda proxy integration). We confirmed via `curl -i` directly against the API Gateway endpoint that AWS silently renames the `WWW-Authenticate` response header to `x-amzn-remapped-www-authenticate` on the way out. We reproduced this on both a REST API and an HTTP API v2 integration, and on a plain Lambda Function URL, and found no proxy-integration setting that overrides it.

Since the MCP spec treats `WWW-Authenticate` on the initial 401 as the trigger for protected-resource-metadata discovery, and observed behavior matches a client that never saw that header, Claude appears to fall back to treating our server's own origin as the authorization server and redirects the user to `/authorize?...`, which doesn't exist on our side, producing a 403/"Forbidden" from AWS's own edge layer.

We worked around it by putting a CloudFront Function in front of API Gateway to restore the header on the way out, and confirmed via `curl -i` through CloudFront that the header arrives correctly again — that's a lot of infrastructure for something that's arguably a client resilience gap, not just a server bug on our end.

### Expected behavior

RFC 9728 §5.3 explicitly documents that a client MAY fall back to fetching `/.well-known/oauth-protected-resource` directly at the resource's origin if the `WWW-Authenticate` challenge is unavailable or doesn't carry `resource_metadata`. Since AWS API Gateway (an extremely common way to host a serverless MCP server) mangles this header in a way that's outside a server developer's control, it would make the Claude MCP client meaningfully more resilient if it attempted this fallback discovery path when the header-based discovery fails or comes back malformed, rather than immediately assuming the resource's own origin is the authorization server.

### Additional context

This looks related to the same general "OAuth discovery goes to the wrong place" failure family as #406 and #644, though the root cause here (AWS API Gateway header remapping) is distinct and, as far as I can tell, not documented anywhere in MCP or Claude connector docs. Flagging in case it saves someone else the debugging loop it cost us — API Gateway + Lambda is a very common MCP hosting pattern.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.