← Back to PRs

#21518: feat(auth): add Anthropic OAuth token refresh and fix external CLI sync

by maxtongwang open 2026-02-20 01:57 View on GitHub →
agents size: L
## Summary - Add `refreshAnthropicTokens` to refresh expired Anthropic OAuth tokens using the Claude platform endpoint, mirroring Claude Code CLI's own refresh flow. On refresh failure, falls back to reading fresh credentials from Claude Code's Keychain before throwing. - Auto-sync Claude Code CLI OAuth credentials into `anthropic:default` during external CLI sync — but only when the existing profile is already OAuth, preventing `api_key`/`token` profiles from being auto-converted. - Extract shared `coerceExpiresAt` helper to `src/agents/oauth-utils.ts`, eliminating duplication between Anthropic and Chutes OAuth modules. ## Fixes vs #8602 This supersedes #8602 with the following improvements: | Fix | Detail | |-----|--------| | Qwen double-read bug | `store.profiles[QWEN_CLI_PROFILE_ID]` was read twice into two separate variables; migrated to use shared `syncExternalCliCredentialsForProvider` like MiniMax/Anthropic | | Testable deps injection | Added optional `deps` param to `syncExternalCliCredentials` to inject credential readers; replaces `vi.mock` ESM pattern that was silently a no-op in Vitest fork pool | | Redundant `String()` casts | Removed `String(cred.provider)` wrappers in `oauth.ts` — already typed as `string` | | Unsafe test cast | Fixed `(result as Record<string, unknown>).email` → `result.email` in `anthropic-oauth.test.ts` | | Stale JSDoc | Updated to mention Claude Code CLI as a sync source | ## Test plan - [x] `src/agents/anthropic-oauth.test.ts` — token refresh, expiry coercion, Keychain fallback shape - [x] `src/agents/auth-profiles/external-cli-sync.test.ts` — sync guardrails: api_key/token profiles not overwritten, stale oauth refreshed, fresh oauth left alone cc @gumadeiras for review --- Generated with [Claude Code](https://claude.com/claude-code)

Most Similar PRs