Skip to content

Return JSON 404 for OAuth discovery when auth is off#4366

Open
JAORMX wants to merge 1 commit intomainfrom
fix/well-known-handler-no-auth
Open

Return JSON 404 for OAuth discovery when auth is off#4366
JAORMX wants to merge 1 commit intomainfrom
fix/well-known-handler-no-auth

Conversation

@JAORMX
Copy link
Collaborator

@JAORMX JAORMX commented Mar 25, 2026

Summary

Claude Code v2.1.83 introduced mandatory OAuth discovery for all HTTP MCP servers — it sends GET /.well-known/oauth-protected-resource before connecting. When the vMCP server (or transparent proxy) has no auth configured, no .well-known handler was registered, so these requests fell through to the / catch-all MCP handler. There, headerValidatingMiddleware rejected the GET with HTTP 406 and a JSON-RPC error body where "error" is an object. Claude Code expects "error" as a string (OAuth error format), Zod validation fails, and it shows "needs authentication" even though no auth is needed.

  • Always register a .well-known/ prefix handler via NewWellKnownHandler, even when AuthInfoHandler is nil
  • When auth is not configured, return HTTP 404 with {"error":"not_found"} JSON — a clean, parseable signal that no auth metadata exists
  • Apply the same fix to both the vMCP server and the transparent proxy

Type of change

  • Bug fix

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)
  • Manual testing (describe below)

Verified that brood-box (which uses the vMCP proxy without auth) builds with a local replace directive and Claude Code v2.1.83 connects without the spurious "needs authentication" prompt.

Changes

File Change
pkg/auth/well_known.go NewWellKnownHandler always returns a handler; nil authInfoHandler → 404 JSON
pkg/auth/well_known_test.go Updated nil case to expect non-nil handler with 404 JSON; updated all 404 body assertions
pkg/vmcp/server/server.go Register .well-known/ prefix unconditionally
pkg/transport/proxy/transparent/transparent_proxy.go Same unconditional registration for transparent proxy

Special notes for reviewers

The root cause is that headerValidatingMiddleware (which guards the MCP handler) returns a JSON-RPC error with "error" as an object, but OAuth discovery clients expect "error" as a string per RFC 6749. Rather than changing the middleware's error format (which is correct for MCP), we prevent OAuth discovery from reaching it at all.

Generated with Claude Code

@github-actions github-actions bot added the size/XL Extra large PR: 1000+ lines changed label Mar 25, 2026
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large PR Detected

This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.

How to unblock this PR:

Add a section to your PR description with the following format:

## Large PR Justification

[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformation

Alternative:

Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.

See our Contributing Guidelines for more details.


This review will be automatically dismissed once you add the justification section.

@codecov
Copy link

codecov bot commented Mar 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.61%. Comparing base (a9f92a0) to head (0b99d31).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4366      +/-   ##
==========================================
+ Coverage   69.55%   69.61%   +0.05%     
==========================================
  Files         480      480              
  Lines       48837    48838       +1     
==========================================
+ Hits        33971    34000      +29     
+ Misses      12249    12220      -29     
- Partials     2617     2618       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Claude Code v2.1.83 sends GET /.well-known/oauth-protected-resource
before connecting to any HTTP MCP server. When auth is not configured,
no .well-known handler was registered, so the request fell through to
the MCP catch-all handler whose headerValidatingMiddleware rejected it
with HTTP 406 and a JSON-RPC error body (where "error" is an object).
Claude Code expects "error" as a string for OAuth errors, causing Zod
validation failure and a spurious "needs authentication" prompt.

Always register a .well-known prefix handler. When AuthInfoHandler is
nil, it returns HTTP 404 with {"error":"not_found"} — a clean signal
that no auth metadata exists and the client should proceed without
authentication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX force-pushed the fix/well-known-handler-no-auth branch from d4f5b5d to 0b99d31 Compare March 25, 2026 15:13
@github-actions github-actions bot added size/XS Extra small PR: < 100 lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Mar 25, 2026
@github-actions github-actions bot dismissed their stale review March 25, 2026 15:14

PR size has been reduced below the XL threshold. Thank you for splitting this up!

@github-actions
Copy link
Contributor

✅ PR size has been reduced below the XL threshold. The size review has been dismissed and this PR can now proceed with normal review. Thank you for splitting this up!

Copy link
Contributor

@amirejaz amirejaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS Extra small PR: < 100 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants