fix(auth): remove ANTHROPIC_API_KEY fallback to prevent silent billing
Remove ANTHROPIC_API_KEY from the authentication fallback chain. Auto Claude is designed to use Claude Code OAuth tokens only. Previously, if CLAUDE_CODE_OAUTH_TOKEN was empty or missing, the system would silently fall back to ANTHROPIC_API_KEY from the environment, causing unexpected API billing when users thought they were using OAuth. Closes #76 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
12c8519246
commit
c52caa6b17
@@ -2,16 +2,17 @@
|
||||
# Copy this file to .env and fill in your values
|
||||
|
||||
# =============================================================================
|
||||
# AUTHENTICATION (REQUIRED - set ONE of the following)
|
||||
# AUTHENTICATION (REQUIRED)
|
||||
# =============================================================================
|
||||
# The framework checks these in order of priority:
|
||||
# 1. CLAUDE_CODE_OAUTH_TOKEN - Original (from `claude setup-token`)
|
||||
# 2. ANTHROPIC_AUTH_TOKEN - For proxies like CCR
|
||||
# 3. ANTHROPIC_API_KEY - Direct Anthropic API key
|
||||
# Auto Claude uses Claude Code OAuth authentication.
|
||||
# Direct API keys (ANTHROPIC_API_KEY) are NOT supported to prevent silent billing.
|
||||
#
|
||||
# Option 1: Run `claude setup-token` to save token to macOS Keychain (recommended)
|
||||
# Option 2: Set the token explicitly:
|
||||
# CLAUDE_CODE_OAUTH_TOKEN=your-oauth-token-here
|
||||
#
|
||||
# For enterprise/proxy setups (CCR):
|
||||
# ANTHROPIC_AUTH_TOKEN=sk-zcf-x-ccr
|
||||
# ANTHROPIC_API_KEY=sk-ant-...
|
||||
|
||||
# =============================================================================
|
||||
# CUSTOM API ENDPOINT (OPTIONAL)
|
||||
|
||||
@@ -96,20 +96,19 @@ def validate_environment(spec_dir: Path) -> bool:
|
||||
"""
|
||||
valid = True
|
||||
|
||||
# Check for authentication token (supports multiple env vars)
|
||||
# Check for OAuth token (API keys are not supported)
|
||||
if not get_auth_token():
|
||||
print("Error: No authentication token found")
|
||||
print(f"\nSet one of: {', '.join(AUTH_TOKEN_ENV_VARS)}")
|
||||
print("\nFor Claude Code CLI, get your OAuth token by running:")
|
||||
print("Error: No OAuth token found")
|
||||
print("\nAuto Claude requires Claude Code OAuth authentication.")
|
||||
print("Direct API keys (ANTHROPIC_API_KEY) are not supported.")
|
||||
print("\nTo authenticate, run:")
|
||||
print(" claude setup-token")
|
||||
print("\nThen set it:")
|
||||
print(" export CLAUDE_CODE_OAUTH_TOKEN='your-token-here'")
|
||||
valid = False
|
||||
else:
|
||||
# Show which auth source is being used
|
||||
source = get_auth_token_source()
|
||||
if source and source != "CLAUDE_CODE_OAUTH_TOKEN":
|
||||
print(f"Auth: Using token from {source}")
|
||||
if source:
|
||||
print(f"Auth: {source}")
|
||||
|
||||
# Show custom base URL if set
|
||||
base_url = os.environ.get("ANTHROPIC_BASE_URL")
|
||||
|
||||
+25
-11
@@ -12,17 +12,19 @@ import platform
|
||||
import subprocess
|
||||
|
||||
# Priority order for auth token resolution
|
||||
# NOTE: We intentionally do NOT fall back to ANTHROPIC_API_KEY.
|
||||
# Auto Claude is designed to use Claude Code OAuth tokens only.
|
||||
# This prevents silent billing to user's API credits when OAuth fails.
|
||||
AUTH_TOKEN_ENV_VARS = [
|
||||
"CLAUDE_CODE_OAUTH_TOKEN", # Original (highest priority)
|
||||
"ANTHROPIC_AUTH_TOKEN", # CCR/proxy token
|
||||
"ANTHROPIC_API_KEY", # Direct API key (lowest priority)
|
||||
"CLAUDE_CODE_OAUTH_TOKEN", # OAuth token from Claude Code CLI
|
||||
"ANTHROPIC_AUTH_TOKEN", # CCR/proxy token (for enterprise setups)
|
||||
]
|
||||
|
||||
# Environment variables to pass through to SDK subprocess
|
||||
# NOTE: ANTHROPIC_API_KEY is intentionally excluded to prevent silent API billing
|
||||
SDK_ENV_VARS = [
|
||||
"ANTHROPIC_BASE_URL",
|
||||
"ANTHROPIC_AUTH_TOKEN",
|
||||
"ANTHROPIC_API_KEY",
|
||||
"NO_PROXY",
|
||||
"DISABLE_TELEMETRY",
|
||||
"DISABLE_COST_WARNINGS",
|
||||
@@ -92,9 +94,11 @@ def get_auth_token() -> str | None:
|
||||
|
||||
Checks multiple sources in priority order:
|
||||
1. CLAUDE_CODE_OAUTH_TOKEN (env var)
|
||||
2. ANTHROPIC_AUTH_TOKEN (ccr/proxy env var)
|
||||
3. ANTHROPIC_API_KEY (direct API key env var)
|
||||
4. macOS Keychain (if on Darwin platform)
|
||||
2. ANTHROPIC_AUTH_TOKEN (CCR/proxy env var for enterprise setups)
|
||||
3. macOS Keychain (if on Darwin platform)
|
||||
|
||||
NOTE: ANTHROPIC_API_KEY is intentionally NOT supported to prevent
|
||||
silent billing to user's API credits when OAuth is misconfigured.
|
||||
|
||||
Returns:
|
||||
Token string if found, None otherwise
|
||||
@@ -133,14 +137,24 @@ def require_auth_token() -> str:
|
||||
token = get_auth_token()
|
||||
if not token:
|
||||
error_msg = (
|
||||
"No authentication token found.\n"
|
||||
f"Set one of: {', '.join(AUTH_TOKEN_ENV_VARS)}\n"
|
||||
"No OAuth token found.\n\n"
|
||||
"Auto Claude requires Claude Code OAuth authentication.\n"
|
||||
"Direct API keys (ANTHROPIC_API_KEY) are not supported.\n\n"
|
||||
)
|
||||
# Provide platform-specific guidance
|
||||
if platform.system() == "Darwin":
|
||||
error_msg += "For Claude Code CLI: run 'claude setup-token' to save token to macOS Keychain"
|
||||
error_msg += (
|
||||
"To authenticate:\n"
|
||||
" 1. Run: claude setup-token\n"
|
||||
" 2. The token will be saved to macOS Keychain automatically\n\n"
|
||||
"Or set CLAUDE_CODE_OAUTH_TOKEN in your .env file."
|
||||
)
|
||||
else:
|
||||
error_msg += "For Claude Code CLI: run 'claude setup-token'"
|
||||
error_msg += (
|
||||
"To authenticate:\n"
|
||||
" 1. Run: claude setup-token\n"
|
||||
" 2. Set CLAUDE_CODE_OAUTH_TOKEN in your .env file"
|
||||
)
|
||||
raise ValueError(error_msg)
|
||||
return token
|
||||
|
||||
|
||||
Reference in New Issue
Block a user