Repository navigation
fix(oauth): 401-triggered OAuth discovery fails for path-based MCP servers due to misrouted resource_metadata URI #18760
Description
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-680packages/core/src/mcp/oauth-utils.ts:discoverOAuthFromWWWAuthenticate()already implements the correct flow but is unused in this code path
Reproduction
- 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" - Configure the MCP server in
~/.gemini/settings.json - Connect -- observe
Failed to handle automatic OAutherror
Context
- This is distinct from OAuth Protected Resource Metadata Discovery Not Following RFC 9728 §3.1 #15754 (fixed by fix(core): use RFC 9728 compliant path-based OAuth protected resource discovery #15756), which addressed the proactive discovery order. This bug is in the reactive (401-triggered) path, which is the primary path taken when servers return
WWW-Authenticateheaders. - The same class of bug was identified in the MCP TypeScript SDK: modelcontextprotocol/typescript-sdk#1450 / PR #1472.
Client Information
CLI Version: 0.28.x (current main)
Activity
[-]handleAutomaticOAuth passes resource_metadata URI to discoverOAuthConfig instead of discoverOAuthFromWWWAuthenticate, breaking 401-triggered OAuth for path-based MCP servers[/-][+]fix(oauth): 401-triggered OAuth discovery fails for path-based MCP servers due to misrouted resource_metadata URI[/+]fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow
Add workaround route for double-nested OAuth metadata path
fix(oauth): use discoverOAuthFromWWWAuthenticate for 401-triggered OA…
yuvrajangadsingh commentedon Feb 20, 2026
/assign
gemini-cli commentedon Feb 20, 2026
👋 @yuvrajangadsingh, you've been assigned to this issue! Thank you for taking the time to contribute. Make sure to check out our contributing guidelines.
fix(oauth): use discoverOAuthFromWWWAuthenticate for 401-triggered OA…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#1…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#1…
Merge(Auto) Commit 'be03e0619': fix: use discoverOAuthFromWWWAuthenti…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#1…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (go…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (go…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (go…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#1…
fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (go…