🔐 PKCE Flow
Claude Code implements OAuth 2.0 Authorization Code flow with PKCE (Proof Key for Code Exchange). Three layers: crypto primitives (verifier, S256 challenge, CSRF state), network client (auth URLs, token exchange, profile), and orchestrator (listener, auto vs manual race).
| Value | How Generated | Purpose |
|---|---|---|
| codeVerifier | 32 random bytes, base64url | Proves this process started the flow |
| codeChallenge | SHA-256(verifier), base64url | Server stores and later verifies |
| state | 32 random bytes, base64url | CSRF protection |
🎯 Auto vs Manual Auth Flow
Automatic (browser redirect)
AuthCodeListener starts HTTP server on OS-assigned port. Browser opens automaticFlowUrl. After login, auth server redirects to localhost. Callback validates state, resolves auth code.
Manual (copy-paste fallback)
Terminal displays manualFlowUrl. User opens URL, authenticates, copies code and pastes into terminal. Used in SSH or unreachable localhost environments.
💡 Race Pattern
Both flows start simultaneously. Whichever delivers an authorization code first wins. The OAuthService races two resolvers against a single Promise.
💳 Token Exchange & Scopes
Authorization code is exchanged for tokens via POST to platform.claude.com/v1/oauth/token. The redirect_uri must exactly match the authorization request.
| Scope | Used For |
|---|---|
| org:create_api_key | Console path - create permanent API key |
| user:profile | Fetch subscription type, rate-limit tier |
| user:inference | Claude.ai path - direct inference via subscription |
| user:sessions:claude_code | Session management for Claude Code client |
| user:mcp_servers | Access MCP servers associated with account |
| user:file_upload | Upload files to Anthropic infrastructure |
📊 Profile & Subscription Types
| Subscription | org_type Key |
|---|---|
| max | claude_max |
| pro | claude_pro |
| team | claude_team |
| enterprise | claude_enterprise |
💡 Profile Skip Optimization
During routine token refresh, if global config already has billingType, accountCreatedAt, subscriptionCreatedAt AND secure storage has non-null subscriptionType and rateLimitTier, the profile call is skipped. This cuts ~7 million requests/day fleet-wide.
🗄️ Token Storage Architecture
macOS
macOsKeychainStorage via security CLI. JSON payload hex-encoded and passed via stdin (-i flag) to keep tokens out of process argument lists.
Linux/Windows
plainTextStorage - encrypted JSON in ~/.claude/ with chmod 0o600.
Stale-while-error
If security subprocess fails transiently, last known good value served from cache.
🔄 Token Refresh & Logout
Access tokens refreshed proactively with 5-minute buffer. Backend allows scope expansion on refresh (ALLOWED_SCOPE_EXPANSIONS).
💡 Telemetry-First Logout
performLogout() flushes telemetry BEFORE clearing credentials. In-flight events carry org attribution; flushing after wipe would send them as anonymous, corrupting usage analytics.