-
Notifications
You must be signed in to change notification settings - Fork 0
Pitfall OAuth Client Max Scope
Affects: OAuth authorization, scope negotiation
Discovered: v1.2.9 (2026-07-05)
Fixed in: v1.2.10
Some OAuth clients (notably Claude.ai) always request all known scopes in the authorize request, regardless of what the server advertises:
scope=content.read+content.write+site.admin+system.admin
Before v1.2.10, the server rejected this with invalid_scope if the client's registered max was lower (e.g. site.admin). This was spec-correct but broke Claude.ai.
See Pitfall invalid-scope disguised as 302 for how this manifested as a silent redirect error.
The authorization server MAY fully or partially ignore the scope requested by the client, based on the authorization server policy or the resource owner's instructions. If the issued access token scope is different from the one requested by the client, the authorization server MUST include the
scoperesponse parameter to inform the client of the actual scope granted.
In other words: clamping is spec-permitted. The server must grant a subset and tell the client which subset it got.
resolveClientScope now clamps instead of rejecting:
if !allowedScope(scope, c.Scope) {
slog.Info("OAuth scope clamped",
"client", clientID,
"requested", scope,
"granted", c.Scope,
"reason", "client_max_scope",
)
scope = c.Scope
}When this happens the server journal (journalctl -u mcp-hugo-server-go) will contain:
INFO OAuth scope clamped client=claude-admin requested=system.admin granted=site.admin reason=client_max_scope
Each client in oauth-clients.yaml has a scope field that is its ceiling. A client can never receive more than this scope, regardless of what it requests:
- client_id: claude-admin
scope: site.admin # ceiling; system.admin requests are clamped here
- client_id: chatgpt-write
scope: content.write # ceiling; any wider request is clamped hereDo not configure a client with scope: system.admin if the intention is site.admin. The scope ceiling is enforced at token issuance, not at the tool call level — but getting it wrong causes confusing authorization errors that look like connectivity issues, not permission errors.