[BUG] Claude Code doesn't use scope from WWW-Authenticate during step-up authorization
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When an MCP server returns HTTP 403 with WWW-Authenticate: Bearer error="insufficient_scope", scope="graph:read", Claude Code initiates a new OAuth flow but does NOT include the indicated scope in its authorization request. This breaks the step-up authorization (upscoping) flow defined in the MCP Authorization spec.
What Should Happen?
Per MCP Authorization Spec Section 2.3.2:
- Client calls a tool with a valid token lacking required scopes
- Server returns
403 Forbiddenwith:
````
WWW-Authenticate: Bearer error="insufficient_scope", scope="graph:read", resource_metadata="..."
- Client extracts
scope="graph:read"from the header - Client initiates OAuth flow requesting
graph:read(plus any existing scopes) - User consents to the specific scope
- Client retries with new token containing
graph:read
Error Messages/Logs
1. ✅ Calls tool with token containing `["openid", "offline_access"]`
2. ✅ Receives 403 with `scope="graph:read"` in WWW-Authenticate
3. ❌ Initiates OAuth flow but only requests `["offline_access", "offline", "openid"]`
4. ❌ New token still only has `["openid", "offline_access"]`
5. ❌ Retry fails with same 403
**The scope from the WWW-Authenticate header is not being parsed and used.**
Steps to Reproduce
- Configure an MCP server that:
- Returns empty
scopes_supportedin/.well-known/oauth-protected-resource - Requires
graph:readscope for a tool - Returns proper RFC 6750
WWW-Authenticateheader on 403
- Connect Claude Code to the server (will auth with minimal scopes since none advertised)
- Call the protected tool
- Observe: Claude Code attempts upscoping but doesn't include the required scope
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.12 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Server 403 Response
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", scope="graph:read", resource_metadata="http://mcp-graph.localhost/.well-known/oauth-protected-resource"
Content-Type: application/json
{"jsonrpc":"2.0","error":{"code":-32001,"message":"insufficient scope, need: graph:read"},"id":1}
Token Before Upscope Attempt
{
"jti": "91e68349-2fc4-453a-919e-05a0af4a2e83",
"scp": ["openid", "offline_access"]
}
OAuth Request During Upscope (from consent server logs)
Processing consent request
client_id=61af3d8d-0615-46b4-bf81-615c45c66573
requested_scopes=["offline_access", "offline", "openid"] ← Missing graph:read!
Token After Upscope Attempt
{
"jti": "d01145d3-a158-4e21-84d7-6bac4bfb607d",
"scp": ["openid", "offline_access"]
}
Note: Different jti confirms a new token was issued, but scopes are identical.
Timeline from Logs
| Time | Event |
| ------------ | ----------------------------------------------------------- |
| 18:37:01.733 | Claude Code calls tools/call with token ...2e83 |
| 18:37:01.734 | Server returns 403 with scope="graph:read" |
| 18:37:01.740 | Claude Code fetches /.well-known/oauth-protected-resource |
| 18:37:01.839 | Claude Code retries with NEW token ...607d (same scopes) |
| 18:37:01.839 | Server returns 403 again (still no graph:read) |
Relevant Specifications
- MCP Authorization Spec - Step-Up Authorization
- RFC 6750 Section 3.1 - WWW-Authenticate with
error="insufficient_scope"
- RFC 9728 - OAuth 2.0 Protected Resource Metadata
Impact
This prevents the "principle of least privilege" flow where:
- Clients start with minimal scopes
- Scopes are requested on-demand when needed
- Users consent to specific scopes for specific operations
Currently, the only workaround is to advertise all possible scopes in scopes_supported, which causes Claude Code to
request everything upfront, putting the burden on users to manually uncheck unwanted scopes.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗