modelcontextprotocol / modelcontextprotocol/go-sdk
RequireBearerToken omits RFC 6750 error code, so the SDK's own step-up flow never triggers
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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