Skip to content

MCP-Proxy WWW-Authenticate Header Parameter Stripping #44

@gazzadownunder

Description

@gazzadownunder

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;
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions