claude-code - 💡(How to fix) Fix Claude Code CLI: OAuth token not auto-refreshed on headless server (refreshToken ignored) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#50743Fetched 2026-04-20 12:14:17
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Author
Timeline (top)
labeled ×4commented ×1

Claude Code CLI does not auto-refresh OAuth tokens when running on a headless Linux server (GCP VM). The .credentials.json file contains a valid refreshToken, but when the accessToken expires, the CLI returns a 401 instead of refreshing.

Root Cause

Claude Code CLI does not auto-refresh OAuth tokens when running on a headless Linux server (GCP VM). The .credentials.json file contains a valid refreshToken, but when the accessToken expires, the CLI returns a 401 instead of refreshing.

Fix Action

Workaround

Currently falling back to a different agent framework (Kenzan) when OAuth is expired, but this means losing access to Claude Code's full toolset (Read, Write, Edit, Bash).

RAW_BUFFERClick to expand / collapse

Description

Claude Code CLI does not auto-refresh OAuth tokens when running on a headless Linux server (GCP VM). The .credentials.json file contains a valid refreshToken, but when the accessToken expires, the CLI returns a 401 instead of refreshing.

Steps to reproduce

  1. Run claude login interactively on a server, authenticate via browser
  2. Wait for accessToken to expire (~6 hours, expiresAt in .credentials.json)
  3. Run claude -p "hello" --output-format stream-json --verbose --dangerously-skip-permissions
  4. Expected: token auto-refreshes using refreshToken
  5. Actual: 401 authentication_error "Invalid authentication credentials"

Environment

  • Claude Code version: 2.1.114
  • OS: Debian 12 (GCP e2-micro VM, headless, no X/display)
  • .credentials.json has valid refreshToken and subscriptionType: "max"
  • No browser available (headless server)

Context

Running Claude Code as a backend agent (called via -p mode from a FastAPI app). The CLI works perfectly when the token is fresh, but silently fails after expiry. Manual token refresh via the OAuth endpoint returns 403 (Cloudflare blocks non-browser requests).

Expected behavior

The CLI should auto-refresh the token using the refreshToken in .credentials.json, similar to how the interactive CLI handles it on desktop machines.

Workaround

Currently falling back to a different agent framework (Kenzan) when OAuth is expired, but this means losing access to Claude Code's full toolset (Read, Write, Edit, Bash).

extent analysis

TL;DR

The Claude Code CLI likely requires modifications to handle headless OAuth token refreshes, as the current implementation relies on interactive browser authentication.

Guidance

  • Investigate the claude login command's authentication flow to understand how it handles token refreshes in interactive mode.
  • Check the Claude Code documentation for any existing configuration options or environment variables that might enable headless token refresh.
  • Consider implementing a custom token refresh mechanism using the refreshToken from the .credentials.json file, potentially by simulating a browser request or using a headless browser library.
  • Verify that the expiresAt value in .credentials.json is correctly updated after a successful token refresh.

Example

No code example is provided due to the lack of specific implementation details in the issue.

Notes

The solution may require modifications to the Claude Code CLI or the development of a custom authentication wrapper to handle headless token refreshes. Additionally, Cloudflare's restrictions on non-browser requests may need to be addressed.

Recommendation

Apply a workaround, such as implementing a custom token refresh mechanism or using a headless browser library, as the current implementation does not support headless OAuth token refreshes.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The CLI should auto-refresh the token using the refreshToken in .credentials.json, similar to how the interactive CLI handles it on desktop machines.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING