Validate Claude Code OAuth imports - #98
Draft
k2v7n24cbf-cyber wants to merge 1 commit into
Draft
Conversation
k2v7n24cbf-cyber
added a commit
to k2v7n24cbf-cyber/openacme
that referenced
this pull request
Jul 22, 2026
Merge staged copy of sandydasari#98 into local-stage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR hardens the Anthropic Claude Code OAuth import/recovery path so OpenAcme does not treat stale Claude Code credentials as a successful login.
Changes:
access_token,refresh_token,expires_at,account_id,mode) instead of comparing onlyaccess_token.Observation
While testing a local OpenAcme deployment using Claude subscription auth, OpenAcme continued failing Anthropic refresh with
invalid_granteven after the Claude account had recently been refreshed/logged in.The local credential inspection was redacted, but the shape was important:
mode: claude-codeand had an expiredexpires_at.~/.claude.jsonhad recent activity.claudeAiOauth) was not present in that recent metadata path.Claude Code-credentials, which still contained the same stale OAuth material.So the user-visible state looked like "Claude was refreshed recently", but OpenAcme was importing a stale credential source and accepting it as valid.
Root Cause
There were three related issues in the Claude Code credential handling:
loginWithClaudeCodeCredentials()blindly imported whatever Claude Code credential was found and returned success. It did not validate whether the credential was already expired or whether its refresh token was still accepted by Anthropic.tryReimportClaudeCode()was designed for silent recovery, but it could silently write expired Claude Code credentials from the keychain. That made recovery loops reload stale material instead of forcing a useful relogin/setup-token path.Reimport idempotence compared only
access_token. If Claude Code rotatedrefresh_tokenor expiry metadata while the access token string stayed the same, OpenAcme considered the credential unchanged and kept the stale refresh metadata.Impact
After this change:
Validation
Local validation run by git hooks and manually while developing:
pnpm --filter @openacme/auth testpnpm --filter @openacme/auth check-typespnpm --filter @openacme/cli check-typespnpm --filter @openacme/server check-typespnpm --filter @openacme/llm-provider check-typespnpm check-typesvia pre-commit hookpnpm testvia pre-commit hookpnpm buildvia pre-push hookpnpm test:e2evia pre-push hookAlso verified in a local production-style OpenAcme install that the patched daemon starts and responds on
/api/healthafter replacing the live bundle.