-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Summary
My previous update to implement the www-authenticate header only provided support for resource_metadata; however, RFC6750 specifies a number of additional parameters. The current implementation strips these other parameters from 401 and 403 responses, violating RFC 6750 and the MCP OAuth 2.1 specification.
Issue: mcp-proxy strips realm, scope, error, and error_description parameters from WWW-Authenticate headers, forwarding only resource_metadata.
Impact: Clients cannot discover required scopes from HTTP headers and must make additional requests to the resource metadata endpoint.
Status: Framework correctly generates full headers per MCP spec; [email protected] strips parameters before forwarding to clients.
Issue: WWW-Authenticate Header Parameter Stripping
Problem Statement
When using [email protected] with OAuth authentication and [email protected], 401 Unauthorized responses are missing required parameters in the WWW-Authenticate header. This breaks the MCP OAuth 2.1 specification which mandates inclusion of realm and scope parameters per RFC 6750.
Expected Behavior (per MCP Specification):
HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Bearer realm="MCP Server", scope="openid", resource_metadata="http://localhost:3000/.well-known/oauth-protected-resource"Actual Behavior ([email protected]):
HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Bearer resource_metadata="http://localhost:3000/.well-known/oauth-protected-resource"Note: The realm and scope parameters are stripped by mcp-proxy even though the MCP OAuth middleware correctly generates them.
Root Cause Analysis
Root Cause: mcp-proxy strips WWW-Authenticate parameters (v5.10.0)
Critical Discovery (2025-01-12): [email protected] extracts the resource_metadata parameter from the WWW-Authenticate header for its internal OAuth discovery logic, but when forwarding the header to HTTP clients, it only includes resource_metadata and strips all other RFC 6750 parameters (realm, scope, error, error_description).
Evidence from Server Logs:
The MCP OAuth middleware correctly generates the full header:
[OAuth Metadata] Generated header: Bearer realm="MCP Server", scope="openid", resource_metadata="http://localhost:3000/.well-known/oauth-protected-resource"
[MCPAuthMiddleware] ✓ WWW-Authenticate header added to Response error
Authentication error: Response {
status: 401,
headers: Headers {
'WWW-Authenticate': 'Bearer realm="MCP Server", scope="openid", resource_metadata="http://localhost:3000/.well-known/oauth-protected-resource"'
}
}
But the HTTP network trace shows:
WWW-Authenticate: Bearer resource_metadata="http://localhost:3000/.well-known/oauth-protected-resource"Root Cause in mcp-proxy Source Code:
File: node_modules/mcp-proxy/dist/index.js (line 945)
/**
* Extract resource_metadata from response header.
*/
function extractResourceMetadataUrl(res) {
const authenticateHeader = res.headers.get("WWW-Authenticate");
if (!authenticateHeader) return;
const [type, scheme] = authenticateHeader.split(" ");
if (type.toLowerCase() !== "bearer" || !scheme) return;
const match = /resource_metadata="([^"]*)"/.exec(authenticateHeader); // ONLY extracts resource_metadata!
if (!match) return;
try {
return new URL(match[1]);
} catch (_a) {
return;
}
}