fix: add user:sessions:claude_code scope to anthropic_oauth_subscription#576
fix: add user:sessions:claude_code scope to anthropic_oauth_subscription#576divybot wants to merge 3 commits into
Conversation
Pushing ANTHROPIC_AUTH_TOKEN forces Claude Code into bearer-proxy mode (precedence #2 in the Anthropic auth ladder), which suppresses the subscription OAuth credentials from `/login` (precedence #6) and disables OAuth-only features like `/remote-control` that require the `user:sessions:claude_code` scope. See anthropics/claude-code#35407 and #48378. The gateway's MITM rewrite of the Authorization header still works without the env var. Workers that have run `claude /login` (or have `~/.claude/.credentials.json` provisioned) send their own subscription bearer, which `InjectHTTP` overwrites with the operator's stored bearer before forwarding upstream. Co-Authored-By: Divy Srivastava <me@littledivy.com>
|
🚀 Preview deployed: https://demo.clawpatrol.dev/pr-preview/pr-576/ Built from |
|
@divybot This is wrong. It must work without |
Reverts the prior approach (stop pushing ANTHROPIC_AUTH_TOKEN) and adds a clawpatrol-side workaround so workers preserve Claude Code OAuth-only features without needing `claude /login` or a hand-provisioned `~/.claude/.credentials.json`. The new shim lives in `clawpatrol run`: when the wrapped command is `claude` and ANTHROPIC_AUTH_TOKEN is in the env, it synthesizes a `.credentials.json` under a clawpatrol-managed CLAUDE_CONFIG_DIR with the placeholder bearer and `user:sessions:claude_code` in the scopes list, then strips ANTHROPIC_AUTH_TOKEN so Claude Code's local auth-mode gate falls through to precedence #6 (subscription OAuth from /login) and exposes `/remote-control`. The gateway's MITM still rewrites Authorization upstream, so the placeholder bytes never reach Anthropic. Non-Claude-Code SDK clients (Python, Node, …) still see ANTHROPIC_AUTH_TOKEN unchanged. Operators can disable the shim with `CLAWPATROL_NO_CLAUDE_OAUTH_SHIM=1`. Also adds `user:sessions:claude_code` to the OAuth subscription plugin's requested scopes — without it the upstream session-register call fails with `OAuth token does not meet scope requirement user:sessions:claude_code` (anthropics/claude-code#33105) even when the local feature flag is satisfied. Co-Authored-By: Divy Srivastava <me@littledivy.com>
|
Re: workers running without
So no The Anthropic-side counterpart: I also added Tests in |
|
Don't like |
Per review: remove the `installClaudeCodeOAuthShim` machinery and the synthesized `CLAUDE_CONFIG_DIR/.credentials.json` it materialized. The hypothesis to test is that Claude Code's `/remote-control` gate is satisfied by the upstream bearer carrying `user:sessions:claude_code` — no local shim required when the gateway's MITM swaps the Authorization header in. What's left: - `anthropic_oauth_subscription.OAuthFlow().Scopes` keeps the newly-added `user:sessions:claude_code` so the operator's stored bearer can pass Anthropic's session-register scope check (anthropics/claude-code#33105). Existing operators reconnect the credential once to pick up the new grant. - `ANTHROPIC_AUTH_TOKEN` env pushdown is unchanged from main. Co-Authored-By: Divy Srivastava <me@littledivy.com>
|
Stripped the shim in Worth flagging: operators who already connected the OAuth subscription credential will need to reconnect once so the stored refresh token picks up the new |
Summary
Adds
user:sessions:claude_codeto the scopesanthropic_oauth_subscriptionrequests during its OAuth handshake. The gateway-stored bearer that the credential plugin swaps into outboundAuthorizationheaders at MITM time now carries the scope Anthropic's session-register endpoint requires for/remote-control.That single-scope change is the whole fix — no clawpatrol-side shim, no synthesized credentials file, no
claude /login, no operator-provisioned~/.claude/.credentials.json. The hypothesis under test (per review): with the upstream bearer carrying the right scope, Claude Code's/remote-controlgate is satisfied even whenANTHROPIC_AUTH_TOKENis in the worker env — the local "bearer-proxy mode disables OAuth features" behavior is just Anthropic's local mirror of the same server-side scope check (anthropics/claude-code#33105).Previous push (
6ecd5ce) layered aninstallClaudeCodeOAuthShimthat synthesized a fake$CLAUDE_CONFIG_DIR/.credentials.jsonand strippedANTHROPIC_AUTH_TOKENfrom the wrapped child's env. That was over-engineered if the scope-only fix works; this push (6394921) deletes the shim and ships the minimal change.Operator impact
ANTHROPIC_AUTH_TOKENenv pushdown is unchanged frommain.user:sessions:claude_codegrant.Test plan
go build ./...cleango vet ./...cleangofmt -l .cleango test -run TestDaemon ./cmd/clawpatrol/...passes (no regressions from the scope edit)clawpatrol run claude→/remote-controlsucceeds end-to-end against ananthropic_oauth_subscription-bound profile. If Claude Code's gate turns out to require something beyond the upstream scope, the shim from6ecd5ceis the fallback.Closes denoland/orchid#171