Skip to content

fix(oauth): 401-triggered OAuth discovery fails for path-based MCP servers due to misrouted resource_metadata URI #18760

@wolf-chili

Description

@wolf-chili

What happened?

When connecting to an OAuth-protected MCP server that returns a WWW-Authenticate header containing resource_metadata, the 401-triggered OAuth flow always fails with ResourceMismatchError. This affects any MCP server that serves resources under a path (e.g., gateways, multi-tenant setups).

The error manifests as:

Failed to handle automatic OAuth for server '<name>'

With the underlying cause being a ResourceMismatchError thrown during metadata validation.

Root Cause

In packages/core/src/tools/mcp-client.ts (line 679-680), handleAutomaticOAuth() parses the resource_metadata URL from the WWW-Authenticate header and passes it to discoverOAuthConfig():

const resourceMetadataUri = OAuthUtils.parseWWWAuthenticateHeader(wwwAuthenticate);
if (resourceMetadataUri) {
  oauthConfig = await OAuthUtils.discoverOAuthConfig(resourceMetadataUri);
}

discoverOAuthConfig() expects a server URL and constructs .well-known paths from it (per RFC 9728 section 3.1). But resourceMetadataUri is already a .well-known URL (e.g., https://example.com/.well-known/oauth-protected-resource), so it produces a double-nested path:

https://example.com/.well-known/oauth-protected-resource/.well-known/oauth-protected-resource

This 404s. The root-based fallback within discoverOAuthConfig then accidentally fetches the root metadata, but validation compares resource: "https://example.com" against expectedResource: "https://example.com/.well-known/oauth-protected-resource" (the metadata URI, not the actual server URL), which throws ResourceMismatchError.

When handleAutomaticOAuth returns false, the caller at line 1702 throws immediately with no fallback to the proactive discovery path (line 1706+), which would have succeeded.

Expected Behavior

handleAutomaticOAuth() should use OAuthUtils.discoverOAuthFromWWWAuthenticate() (which already exists at oauth-utils.ts line 332) to directly fetch the resource_metadata URL and validate against the actual server URL:

// Current (buggy):
oauthConfig = await OAuthUtils.discoverOAuthConfig(resourceMetadataUri);

// Suggested fix:
const serverUrl = mcpServerConfig.httpUrl || mcpServerConfig.url!;
oauthConfig = await OAuthUtils.discoverOAuthFromWWWAuthenticate(wwwAuthenticate, serverUrl);

Affected Code

  • packages/core/src/tools/mcp-client.ts: handleAutomaticOAuth() lines 679-680
  • packages/core/src/mcp/oauth-utils.ts: discoverOAuthFromWWWAuthenticate() already implements the correct flow but is unused in this code path

Reproduction

  1. Set up an MCP server behind a path (e.g., https://gateway.example.com/ns/server/mcp) that returns:
    WWW-Authenticate: Bearer resource_metadata="https://gateway.example.com/.well-known/oauth-protected-resource"
    
  2. Configure the MCP server in ~/.gemini/settings.json
  3. Connect -- observe Failed to handle automatic OAuth error

Context

Client Information

CLI Version: 0.28.x (current main)

Metadata

Metadata

Labels

area/coreIssues related to User Interface, OS Support, Core Functionalityhelp wantedWe will accept PRs from all issues marked as "help wanted". Thanks for your support!priority/p2Important but can be addressed in a future release.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions