anthropics / anthropics/claude-code
HTTP MCP OAuth: pending flow state lost across a turn boundary, breaks manual complete_authentication on remote sessions
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
**Environment:**
- Claude Code version: 2.1.267 (native install)
- Session type: remote/sandboxed (browser's `localhost:` redirect is not reachable from the session — confirmed via `lsof`/`curl`, nothing listens on that port from the session's own network namespace)
- MCP server: HTTP-type with OAuth (`"type": "http"`, `oauth.clientId` + `oauth.callbackPort` in `.claude.json`), specifically an `Org62-Sobject-Read` server pointing at `https://api.salesforce.com/platform/mcp/v1/platform/sobject-reads`
**Summary:**
For an HTTP MCP server configured with OAuth, calling `authenticate` followed later by `complete_authentication` (the documented fallback for remote sessions, where the redirect page can't load) fails with `"No OAuth flow is in progress for . Call authenticate first, then retry with the callback URL."` — even when the callback URL's `state` matches exactly what `authenticate` just returned, and even when the user completes the browser login as fast as possible.
**Repro steps:**
1. In a remote/sandboxed Claude Code session, call `__authenticate`. Receive an authorization URL with a `code_challenge`/`state`.
2. Open the URL in a browser, complete login/consent. Browser redirects to `http://localhost:/callback?code=...&state=...` — page fails to load (expected in remote sessions per the tool's own docs), but the URL is captured from the address bar.
3. Call `__complete_authentication` with that exact callback URL.
4. **Actual:** `"No OAuth flow is in progress for ..."` — every time, regardless of how quickly step 3 follows step 2.
5. **Expected:** the flow completes and exchanges the code for a token.
**Isolating evidence:**
Called `authenticate` and *immediately* (same turn, no user round trip, near-zero delay) called `complete_authentication` with a deliberately fake code. That returned a *different* error: `"Authentication failed for : retry your request"` — i.e., the pending flow *was* found and it proceeded to attempt a token exchange (which correctly failed on the bogus code). This shows the pending-flow state exists and is briefly valid immediately after `authenticate`, but does not survive a normal turn boundary (assistant sends message → waits for user → user replies), which is unavoidable for any real browser-based OAuth login. This makes the manual `complete_authentication` fallback effectively non-functional for HTTP MCP OAuth on remote sessions.
**Suspected cause:** pending OAuth flow state (PKCE verifier + expected state) for HTTP MCP OAuth appears to be held in memory scoped to a single turn/tool-execution context rather than persisted for the lifetime of the flow, so it's discarded before a human can complete the browser step and report back.
**Secondary note (unrelated, encountered while diagnosing):** hitting the generic `login.salesforce.com` domain (rather than the org's My Domain) for this particular External Client App produced `OAUTH_AUTHORIZATION_BLOCKED - Cross-org OAuth flows are not supported for this external client app` — resolved by using "Use Custom Domain" to the org's actual My Domain. Not a Claude Code bug, but worth noting since it compounds the above (extra turns spent on login retries before ever reaching the state-loss issue).
🤖 Filed via Claude Code
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the HTTP MCP `authenticate` and `complete_authentication` tool entry points, using the `.claude.json` OAuth configuration and the callback URL described in the report. Compare pending-flow lifetime across the immediate same-turn fake-code case and a normal turn boundary. Done means a matching callback can find the pending flow and exchange its code for a token in a remote session.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, authentication
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100