#21518: feat(auth): add Anthropic OAuth token refresh and fix external CLI sync
agents
size: L
Cluster:
Auth Improvements and Fixes
## 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
#2123: fix(auth): sync from Claude CLI keychain before OAuth refresh
by jorge123255 · 2026-01-26
80.4%
#7523: fix(auth): re-sync external CLI credentials on token revocation
by codeslayer44 · 2026-02-02
79.6%
#10492: fix(auth): store Anthropic setup-token as type:oauth for auto-refresh
by sparck75 · 2026-02-06
79.5%
#13484: feat(auth): restore Claude Code CLI OAuth credential sync
by joshpocock · 2026-02-10
77.8%
#22105: feat(auth): add refreshable Anthropic OAuth login flow
by sauerdaniel · 2026-02-20
76.5%
#10108: fix: override stale Anthropic OAuth stealth headers for Opus 4.6
by CivilBooks · 2026-02-06
74.3%
#3196: docs: clarify auth-profiles.json format for Claude Max setup-tokens
by aadeina · 2026-01-28
73.6%
#23700: feat: Claude CLI personal-use auth (no API key required) + native A...
by 88plug · 2026-02-22
72.7%
#4550: fix: sync google-gemini-cli-auth tokens from external CLI (#3803)
by SalimBinYousuf1 · 2026-01-30
72.2%
#18670: feat: add first-class Claude Code CLI auth path + CLI model UX hard...
by SmithLabsLLC · 2026-02-16
72.0%