Skip to content

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

Open
maxtongwang wants to merge 1 commit intoopenclaw:mainfrom
maxtongwang:fix/anthropic-oauth-upstream
Open

feat(auth): add Anthropic OAuth token refresh and fix external CLI sync#21518
maxtongwang wants to merge 1 commit intoopenclaw:mainfrom
maxtongwang:fix/anthropic-oauth-upstream

Conversation

@maxtongwang
Copy link

@maxtongwang maxtongwang commented Feb 20, 2026

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>).emailresult.email in anthropic-oauth.test.ts
Stale JSDoc Updated to mention Claude Code CLI as a sync source

Test plan

  • src/agents/anthropic-oauth.test.ts — token refresh, expiry coercion, Keychain fallback shape
  • 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

- Add `refreshAnthropicTokens` to refresh expired Anthropic OAuth tokens
  using the Claude platform endpoint, mirroring Claude Code CLI's own
  refresh flow. Includes Keychain fallback: if refresh fails, reads fresh
  credentials from Claude Code CLI 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 — prevents 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.
- Fix `syncExternalCliCredentials`: migrate Qwen sync block to use shared
  `syncExternalCliCredentialsForProvider` helper, eliminating a double-read
  bug and ~20 lines of duplicate logic.
- Add optional `deps` parameter to `syncExternalCliCredentials` for
  testable credential-reader injection (replaces broken vi.mock ESM pattern).
- Remove redundant `String(cred.provider)` wrappers in `oauth.ts`.
- Fix unsafe cast in `anthropic-oauth.test.ts`: use `result.email` directly.

Supersedes openclaw#8602.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: L labels Feb 20, 2026
@anieve01
Copy link

Great, Looking forward to the merge of this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments