Skip to content

fix: re-auth on stale OAuth token; read Claude Code credentials from macOS Keychain - #12971

Closed
5park1e wants to merge 1 commit into
NousResearch:mainfrom
5park1e:fix/anthropic-oauth-keychain-bugs
Closed

5park1e wants to merge 1 commit into
NousResearch:mainfrom
5park1e:fix/anthropic-oauth-keychain-bugs

Conversation

@5park1e

@5park1e 5park1e commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #12905 — two bugs in the Anthropic provider OAuth flow:

### Bug 3: Stale OAuth token not detected in `hermes model`

`_model_flow_anthropic` used `has_creds = bool(existing_key)` which treats any non-empty token (including expired OAuth tokens) as valid. This caused `hermes model` to skip the re-auth flow entirely when only a stale OAuth token was present.

**Fix**: Added `existing_is_stale_oauth` check — if the only credential is an OAuth token (`sk-ant-` prefix) with no valid `cc_creds` fallback, mark it stale and force the re-auth menu.

### Bug 4: macOS Keychain credentials never read

Claude Code >=2.1.114 migrated credentials from `~/.claude/.credentials.json` to the macOS Keychain under service `"Claude Code-credentials"`. `read_claude_code_credentials()` only read the JSON file, so credentials were silently unavailable.

**Fix**: Added `_read_claude_code_credentials_from_keychain()` using the `security` CLI. `read_claude_code_credentials()` now tries Keychain first (Darwin only) then falls back to the JSON file.

## Changes

| File | Change |
|------|--------|
| `hermes_cli/main.py` | +11 lines: stale OAuth detection before `has_creds` |
| `agent/anthropic_adapter.py` | +72 lines: Keychain read via `security` CLI + Keychain-first lookup |
| `tests/agent/test_anthropic_keychain.py` | NEW (165 lines, 11 cases) |
| `tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py` | NEW (210 lines, 8 cases) |

## Test Plan

- [x] New unit tests added (19 cases total)
- [ ] Manual testing on macOS with Claude Code >=2.1.114
- [ ] Manual testing with expired OAuth token in `.env`

## Type of Change

- [x] 🐛 Bug fix (non-breaking change that fixes an issue)
- [ ] ✅ Tests (adding or improving test coverage)

## Checklist

- [x] I've read the Contributing Guide
- [x] My commit messages follow Conventional Commits
- [x] My PR contains only changes related to this fix
- [ ] I've tested on macOS (required for Bug 4 Keychain testing)

…macOS Keychain

Bug 3 — Stale OAuth token not detected in 'hermes model':
- _model_flow_anthropic used 'has_creds = bool(existing_key)' which treats
  any non-empty token (including expired OAuth tokens) as valid.
- Added existing_is_stale_oauth check: if the only credential is an OAuth
  token (sk-ant- prefix) with no valid cc_creds fallback, mark it stale
  and force the re-auth menu instead of silently accepting a broken token.

Bug 4 — macOS Keychain credentials never read:
- Claude Code >=2.1.114 migrated from ~/.claude/.credentials.json to the
  macOS Keychain under service 'Claude Code-credentials'.
- Added _read_claude_code_credentials_from_keychain() using the 'security'
  CLI tool; read_claude_code_credentials() now tries Keychain first then
  falls back to JSON file.
- Non-Darwin platforms return None from Keychain read immediately.

Tests:
- tests/agent/test_anthropic_keychain.py: 11 cases covering Darwin-only
  guard, security command failures, JSON parsing, fallback priority.
- tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py: 8 cases
  covering stale OAuth detection, API key passthrough, cc_creds fallback.

Refs: NousResearch#12905
@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for the contribution, @5park1e! Both fixes from this PR have already landed on main via your own commit.

This is an automated hermes-sweeper review.

Evidence:

  • Commit e1106772dfix: re-auth on stale OAuth token; read Claude Code credentials from macOS Keychain — is confirmed reachable from main (git branch --contains e1106772d* main).
  • hermes_cli/main.py lines 4346–4350: existing_is_stale_oauth detection present.
  • agent/anthropic_adapter.py line 470: _read_claude_code_credentials_from_keychain() defined and called at line 545.
  • Both new test files (tests/agent/test_anthropic_keychain.py, tests/hermes_cli/test_anthropic_model_flow_stale_oauth.py) exist on disk.

The commit landed after the v2026.4.23 release tag, so it will ship in the next tagged release. Closing as implemented.

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

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P1 High — major feature broken, no workaround provider/anthropic Anthropic native Messages API type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants