Skip to content

Auth middleware returns plain text 401 instead of RFC 6750 compliant JSON error response #4055

@amirejaz

Description

@amirejaz

Description

When a request arrives at the vMCP (or MCPServer) without an Authorization header, the auth middleware returns a 401 response with a plain text body:

authorization header required

RFC 6750 Section 3 requires the error response body to be JSON:

{
  "error": "invalid_token",
  "error_description": "authorization header required"
}

The Content-Type header is also incorrectly set to text/plain; charset=utf-8 instead of application/json.

Impact

Any RFC 6750-compliant OAuth client that tries to parse the 401 response body as JSON will fail. This is observed with Claude Code, which surfaces the following error:

Error: HTTP 401: Invalid OAuth error response: SyntaxError: JSON Parse error: Unexpected identifier "authorization". Raw body: authorization header required

Root Cause

In pkg/auth/token.go, the Middleware function calls http.Error(w, err.Error(), http.StatusUnauthorized) when the Authorization header is missing. http.Error sets Content-Type: text/plain and writes the raw error string as the body.

tokenString, err := ExtractBearerToken(r)
if err != nil {
    w.Header().Set("WWW-Authenticate", v.buildWWWAuthenticate(false, ""))
    http.Error(w, err.Error(), http.StatusUnauthorized) // plain text, not JSON
    return
}

Expected Behaviour

The 401 response should:

  • Set Content-Type: application/json
  • Return a JSON body conforming to RFC 6750 Section 3

Steps to Reproduce

  1. Configure a VirtualMCPServer with incomingAuth.type: oidc
  2. Connect with an MCP client (e.g. Claude Code) without a valid Bearer token
  3. Observe the 401 response with plain text body

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions