Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Appendix G: Authentication & Subscription System — From OAuth to Compliance Boundaries

This appendix analyzes the authentication architecture and subscription system of Claude Code v2.1.88 based on its source code, and examines the compliance boundaries for developers building Agents in the context of Anthropic's April 2026 ban on third-party tools.

G.1 Dual-Track OAuth Authentication Architecture

Claude Code supports two distinctly different authentication paths, serving two types of user groups.

G.1.1 Claude.ai Subscription Users

Subscription users (Pro/Max/Team/Enterprise) authenticate through Claude.ai's OAuth endpoint:

User → claude login → claude.com/cai/oauth/authorize
  → Authorization page (PKCE flow)
  → Callback → exchangeCodeForTokens()
  → OAuth access_token + refresh_token
  → Use token directly to call Anthropic API (no API key needed)
// restored-src/src/constants/oauth.ts:18-20
const CLAUDE_AI_INFERENCE_SCOPE = 'user:inference'
const CLAUDE_AI_PROFILE_SCOPE = 'user:profile'

Key scopes:

  • user:inference — Permission to invoke the model
  • user:profile — Read account information
  • user:sessions — Session management
  • user:mcp — MCP server access
  • user:file_upload — File upload

OAuth configuration (restored-src/src/constants/oauth.ts:60-234):

ConfigurationProduction Value
Authorization URLhttps://claude.com/cai/oauth/authorize
Token URLhttps://platform.claude.com/v1/oauth/token
Client ID9d1c250a-e61b-44d9-88ed-5944d1962f5e
PKCERequired (S256)

G.1.2 Console API Users

Console users (pay-as-you-go) authenticate through the Anthropic developer platform:

User → claude login → platform.claude.com/oauth/authorize
  → Authorization (scope: org:create_api_key)
  → Callback → exchangeCodeForTokens()
  → OAuth token → createAndStoreApiKey()
  → Generate temporary API key → Use key to call API

The difference: Console users have an additional step — after OAuth, an API key is created, and actual API calls use key-based authentication rather than token-based authentication.

G.1.3 Third-Party Providers

In addition to Anthropic's own authentication, Claude Code also supports:

ProviderEnvironment VariableAuthentication Method
AWS BedrockCLAUDE_CODE_USE_BEDROCK=1AWS credential chain
GCP Vertex AICLAUDE_CODE_USE_VERTEX=1GCP credentials
Azure FoundryCLAUDE_CODE_USE_FOUNDRY=1Azure credentials
Direct API keyANTHROPIC_API_KEY=sk-...Direct passthrough
API Key HelperapiKeyHelper configCustom command
// restored-src/src/utils/auth.ts:208-212
type ApiKeySource =
  | 'ANTHROPIC_API_KEY'     // Environment variable
  | 'apiKeyHelper'          // Custom command
  | '/login managed key'    // OAuth-generated key
  | 'none'                  // No authentication

G.2 Subscription Tiers and Rate Limits

G.2.1 Four-Tier Subscriptions

The subscription detection function in the source code (restored-src/src/utils/auth.ts:1662-1711) reveals the complete tier hierarchy:

TierOrganization TypeRate MultiplierPrice (Monthly)
Proclaude_pro1x$20
Maxclaude_max5x or 20x$100 / $200
Teamclaude_team5x (Premium)Per seat
Enterpriseclaude_enterpriseCustomBy contract
// restored-src/src/utils/auth.ts:1662-1711
function getSubscriptionType(): 'max' | 'pro' | 'team' | 'enterprise' | null
function isMaxSubscriber(): boolean
function isTeamPremiumSubscriber(): boolean  // Team with 5x rate limit
function getRateLimitTier(): string  // e.g., 'default_claude_max_20x'

G.2.2 Rate Limit Tiers

The values returned by getRateLimitTier() directly affect the API call frequency cap:

  • default_claude_max_20x — Max highest tier, 20x the default rate
  • default_claude_max_5x — Max standard tier / Team Premium
  • Default — Pro and regular Team

G.2.3 Extra Usage

Certain operations trigger additional billing (restored-src/src/utils/extraUsage.ts:4-24):

function isBilledAsExtraUsage(): boolean {
  // The following cases trigger Extra Usage billing:
  // 1. Claude.ai subscription users using Fast Mode
  // 2. Using 1M context window models (Opus 4.6, Sonnet 4.6)
}

Supported billing types:

  • stripe_subscription — Standard Stripe subscription
  • stripe_subscription_contracted — Contract-based
  • apple_subscription — Apple IAP
  • google_play_subscription — Google Play

G.3 Token Management and Secure Storage

G.3.1 Token Lifecycle

Obtain token → Store in macOS Keychain → Read from Keychain when needed
  → Auto-refresh 5 minutes before expiry → Retry on refresh failure (up to 3 times)
  → All retries fail → Prompt user to re-login

Key implementation (restored-src/src/utils/auth.ts):

// Expiry check: 5-minute buffer
function isOAuthTokenExpired(token): boolean {
  return token.expires_at < Date.now() + 5 * 60 * 1000
}

// Auto-refresh
async function checkAndRefreshOAuthTokenIfNeeded() {
  // Token refresh with retry logic
  // Clears cache on failure, re-fetches on next call
}

G.3.2 Secure Storage

  • macOS: Keychain Services (encrypted storage)
  • Linux: libsecret / filesystem fallback
  • Subprocess passing: Via File Descriptor (CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR), avoiding environment variable leakage
  • API Key Helper: Supports custom commands to obtain keys, with a default 5-minute cache TTL

G.3.3 Logout Cleanup

performLogout() (restored-src/src/commands/logout/logout.tsx:16-48) performs a complete cleanup:

  1. Flush telemetry data (ensure nothing is lost)
  2. Remove API key
  3. Wipe all credentials from Keychain
  4. Clear OAuth account information from configuration
  5. Optional: Clear onboarding state
  6. Invalidate all caches: OAuth token, user data, beta features, GrowthBook, policy limits

G.4 Permissions and Roles

The organization role returned by the OAuth profile determines the user's capability boundaries:

// restored-src/src/utils/billing.ts
// Console billing access
function hasConsoleBillingAccess(): boolean {
  // Requires: non-subscription user + admin or billing role
}

// Claude.ai billing access
function hasClaudeAiBillingAccess(): boolean {
  // Max/Pro automatically have access
  // Team/Enterprise require admin, billing, owner, or primary_owner
}
CapabilityRequired Role
Access Console billingadmin or billing (non-subscription users)
Access Claude.ai billingMax/Pro automatic; Team/Enterprise require admin/billing/owner
Extra usage toggleClaude.ai subscription + supported billingType
/upgrade commandNon-Max 20x users

G.5 Telemetry and Account Tracking

The authentication system is deeply integrated with telemetry (restored-src/src/services/analytics/metadata.ts):

  • isClaudeAiAuth — Whether Claude.ai authentication is being used
  • subscriptionType — Used for DAU-by-tier analysis
  • accountUuid / emailAddress — Passed in telemetry headers

Key analytics events:

tengu_oauth_flow_start          → OAuth flow initiated
tengu_oauth_success             → OAuth successful
tengu_oauth_token_refresh_success/failure → Token refresh result
tengu_oauth_profile_fetch_success → Profile fetch successful

G.6 Compliance Boundary Analysis

G.6.1 Background: The April 2026 OpenClaw Incident

In April 2026, Anthropic officially banned third-party tools from using subscription quotas via OAuth. The core reasons:

  1. Unsustainable costs: Tools like OpenClaw ran automated Agents 24/7, consuming $1,000-5,000 in daily API costs — far exceeding what a $200/month Max subscription could cover
  2. Bypassing cache optimization: Claude Code's four-layer prompt cache (see Chapters 13-14) can reduce costs by 90%; third-party tools calling the API directly result in 100% cache misses
  3. Terms modification: The OAuth user:inference scope was restricted to official product usage only

G.6.2 Behavior Classification

BehaviorTechnical ImplementationRisk Level
Manual use of Claude Code CLIInteractive claude commandSafe — Intended use of the official product
Scripted claude -p callsShell script automationSafe — Officially supported non-interactive mode
cc-sdk launching claude subprocesscc_sdk::query() / cc_sdk::llm::query()Low risk — Goes through the full CLI pipeline (including cache)
MCP Server called by Claude Codermcp / MCP protocolSafe — Official extension mechanism
Agent SDK building personal tools@anthropic-ai/claude-code SDKSafe — Intended use of the official SDK
Extracting OAuth token to call API directlyBypassing Claude Code CLIHigh risk — This is the banned behavior
Automation in CI/CDclaude -p in CIGray area — Depends on frequency and usage
Distributing open-source tools that depend on claudeUsers authenticate themselvesGray area — Depends on usage patterns
24/7 automated daemonContinuous subscription quota consumptionHigh risk — The OpenClaw pattern

G.6.3 The Key Distinction: Whether You Go Through Claude Code's Infrastructure

This is the most critical criterion:

Safe path:
  Your code → cc-sdk → claude CLI subprocess → CC infrastructure (with cache) → API
  ↑ Goes through prompt cache, Anthropic's costs stay manageable

Dangerous path:
  Your code → Extract OAuth token → Call Anthropic API directly
  ↑ Bypasses prompt cache, every request is full price

Claude Code's getCacheControl() function (restored-src/src/services/api/claude.ts:358-374) carefully designs three-level cache breakpoints: global, organization, and session. Requests sent through the CLI automatically benefit from this cache optimization. Third-party tools calling the API directly cannot reuse these caches — this is the root cause of the cost problem.

Quick Check: Does it spawn a claude subprocess?

This is the simplest compliance criterion. All approaches that communicate through a claude CLI subprocess go through CC's full infrastructure (prompt cache + telemetry + permission checks), keeping Anthropic's costs manageable; calling the API directly bypasses everything.

ApproachSpawns process?Compliant
cc-sdk query()Yes — Command::new("claude")Compliant
cc-sdk llm::query()Yes — same, plus --tools ""Compliant
Agent SDK (@anthropic-ai/claude-code)Yes — official SDK spawns claudeCompliant
claude -p "..." Shell scriptYesCompliant
MCP Server called by CCYes — CC initiates itCompliant
Extract OAuth token -> fetch("api.anthropic.com")No — bypasses CLINon-compliant
OpenClaw and other third-party AgentsNo — calls API directlyNon-compliant

G.6.4 Compliance of This Book's Example Code

The Code Review Agent in Chapter 30 of this book uses the following approaches:

BackendImplementationCompliance
CcSdkBackendcc-sdk launching claude CLI subprocessCompliant — Goes through the official CLI
CcSdkWsBackendWebSocket connection to CC instanceCompliant — Goes through the official protocol
CodexBackendCodex subscription (OpenAI, not Anthropic)Not applicable — Does not involve Anthropic
MCP Server modeClaude Code calling via MCPCompliant — Official extension mechanism

Recommendations:

  1. Do not extract OAuth tokens from ~/.claude/ for other purposes
  2. Do not build 24/7 automated daemons
  3. Retain CodexBackend as an alternative that does not depend on Anthropic subscriptions
  4. If high-frequency automation is needed, use API key pay-as-you-go billing instead of subscriptions

G.7 Key Environment Variable Index

VariablePurposeSource
ANTHROPIC_API_KEYDirect API keyUser-configured
CLAUDE_CODE_OAUTH_REFRESH_TOKENPre-authenticated refresh tokenAutomated deployments
CLAUDE_CODE_OAUTH_SCOPESScopes for the refresh tokenUsed with the above
CLAUDE_CODE_ACCOUNT_UUIDAccount UUID (for SDK callers)SDK integration
CLAUDE_CODE_USER_EMAILUser email (for SDK callers)SDK integration
CLAUDE_CODE_ORGANIZATION_UUIDOrganization UUIDSDK integration
CLAUDE_CODE_USE_BEDROCKEnable AWS BedrockThird-party integration
CLAUDE_CODE_USE_VERTEXEnable GCP Vertex AIThird-party integration
CLAUDE_CODE_USE_FOUNDRYEnable Azure FoundryThird-party integration
CLAUDE_CODE_API_KEY_FILE_DESCRIPTORFile descriptor for API keySecure passing
CLAUDE_CODE_CUSTOM_OAUTH_URLCustom OAuth endpointFedStart deployments