modelcontextprotocol / modelcontextprotocol/go-sdk

RequireBearerToken omits RFC 6750 error code, so the SDK's own step-up flow never triggers

Open
#1,134 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

P2
Dominant language
Go
Stars
5.1k
Forks
543
Avg merge
1d 17h
Merged PRs (30d)
37

Description

Describe the bug

RequireBearerToken (auth/auth.go) never adds an error= auth-param to the WWW-Authenticate challenge it emits. On insufficient scope it returns 403 with a header like:

WWW-Authenticate: Bearer resource_metadata="...", scope="admin"

with no error="insufficient_scope".

But the SDK's own client gates step-up re-authorization on exactly that value (auth/authorization_code.go, AuthorizationCodeHandler.Authorize):

if resp.StatusCode == http.StatusForbidden && errorFromChallenges(wwwChallenges) != "insufficient_scope" {
    // We only want to perform step-up authorization for insufficient_scope errors.
    return nil
}

errorFromChallenges reads Params["error"]; since the server never sets it, it returns "", the condition is true, and Authorize returns without ever performing step-up — even though the required scopes were advertised via scope. So an SDK client hitting an SDK server that needs more scopes is never prompted to re-authorize; the call just keeps failing with 403 instead of upgrading scopes (the step-up flow).

It's also an RFC 6750 §3.1 deviation: the error code (insufficient_scope on 403, invalid_token on the token-invalid 401s) should be advertised in the challenge.

To Reproduce

Wrap a handler with RequireBearerToken(verifier, &RequireBearerTokenOptions{Scopes: []string{"admin"}, ResourceMetadataURL: "..."}), present a valid token whose Scopes lack admin, and inspect the response: 403 with a WWW-Authenticate header that contains scope="admin" but no error="insufficient_scope". Feeding that response to the SDK client's Authorize skips step-up.

Expected behavior

The WWW-Authenticate challenge on a 401/403 should carry the RFC 6750 error code (error="insufficient_scope" / error="invalid_token"), so clients — including the SDK's own step-up flow — can react.

I have a fix ready (threads the error code out of verify and adds the error= param; additive, non-breaking) and will open a PR referencing this issue.

Version

main / v1.7.0.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in auth/auth.go at RequireBearerToken and its verify path, then read auth/authorization_code.go to understand how Authorize consumes WWW-Authenticate challenges. Reproduce the insufficient-scope case with the documented RequireBearerTokenOptions and inspect the 403 and 401 headers. Done means the challenges advertise the RFC 6750 error values and the SDK step-up flow can recognize insufficient_scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, authentication
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.