From 19c8ad3d3d612b1ef74d80ea1a9035ac9d0d3e0f Mon Sep 17 00:00:00 2001 From: teknium1 Date: Mon, 16 Mar 2026 23:26:43 -0700 Subject: [PATCH] fix: add Claude Code user-agent to OAuth token exchange/refresh requests Anthropic's token endpoint is behind Cloudflare which blocks Python's default urllib user-agent (Python-urllib/3.x). Without a proper user-agent, the token exchange returns 403 (Cloudflare error 1010). Adds 'claude-cli/2.1.2 (external, cli)' user-agent to all three OAuth HTTP requests: - Initial token exchange (authorization_code grant) - Hermes token refresh (refresh_token grant) - Claude Code credential refresh (refresh_token grant) Verified: full OAuth PKCE flow now works end-to-end. --- agent/anthropic_adapter.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/agent/anthropic_adapter.py b/agent/anthropic_adapter.py index 79f8ac1a..8b6039b9 100644 --- a/agent/anthropic_adapter.py +++ b/agent/anthropic_adapter.py @@ -200,7 +200,10 @@ def _refresh_oauth_token(creds: Dict[str, Any]) -> Optional[str]: req = urllib.request.Request( "https://console.anthropic.com/v1/oauth/token", data=data, - headers={"Content-Type": "application/x-www-form-urlencoded"}, + headers={ + "Content-Type": "application/x-www-form-urlencoded", + "User-Agent": f"claude-cli/{_CLAUDE_CODE_VERSION} (external, cli)", + }, method="POST", ) @@ -510,7 +513,10 @@ def run_hermes_oauth_login() -> Optional[str]: req = urllib.request.Request( _OAUTH_TOKEN_URL, data=exchange_data, - headers={"Content-Type": "application/json"}, + headers={ + "Content-Type": "application/json", + "User-Agent": f"claude-cli/{_CLAUDE_CODE_VERSION} (external, cli)", + }, method="POST", ) @@ -588,7 +594,10 @@ def refresh_hermes_oauth_token() -> Optional[str]: req = urllib.request.Request( _OAUTH_TOKEN_URL, data=data, - headers={"Content-Type": "application/json"}, + headers={ + "Content-Type": "application/json", + "User-Agent": f"claude-cli/{_CLAUDE_CODE_VERSION} (external, cli)", + }, method="POST", )