Skip to content

Pitfall OAuth Client Max Scope

Jm Rohmer edited this page Jul 5, 2026 · 2 revisions

Pitfall: OAuth client max scope and scope clamping

Affects: OAuth authorization, scope negotiation
Discovered: v1.2.9 (2026-07-05)
Fixed in: v1.2.10


The problem

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.


RFC 6749 §3.3 — the spec answer

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 scope response 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.


Fix: scope clamping (v1.2.10)

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

Client configuration

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 here

Lesson

Do 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.

Clone this wiki locally