OAuth access token not auto-refreshed — daily re-login required for subscription users

Resolved 💬 3 comments Opened Apr 3, 2026 by klysdale Closed Apr 6, 2026

Summary

Claude Code prompts for a full OAuth re-login every ~24 hours instead of silently refreshing using the stored refresh token.

Environment

  • Platform: macOS (darwin 25.3.0)
  • Auth method: Claude.ai Pro subscription (OAuth)
  • Shell: zsh

Behavior

After logging in via \/login\, the credentials are saved to \~/.claude/.credentials.json\ with both an \accessToken\ and a \refreshToken\. However, the access token has a TTL of approximately 24 hours (confirmed via the \expiresAt\ field). When it expires, Claude Code does not silently refresh using the refresh token — it instead requires a full browser-based OAuth re-login.

This has been happening consistently for several weeks.

Expected Behavior

Claude Code should detect an expired access token and automatically exchange the stored \refreshToken\ for a new access token without user interaction — standard OAuth 2.0 refresh flow.

Actual Behavior

Claude Code prompts the user to run \/login\ and complete the browser OAuth flow again, every single day.

Impact

This breaks agentic/automated workflows for subscription users. The daily interruption requires manual intervention and prevents Claude Code from running autonomously in background agents or scheduled tasks.

Credentials File Structure (sanitized)

{
  "claudeAiOauth": {
    "accessToken": "[REDACTED]",
    "refreshToken": "[REDACTED]",
    "expiresAt": 1775212290694,
    "scopes": ["user:file_upload", "user:inference", "user:mcp_servers", "user:profile", "user:sessions:claude_code"],
    "subscriptionType": "pro",
    "rateLimitTier": "default_claude_ai"
  }
}

The \expiresAt\ timestamp resolves to approximately 24 hours after login. The refresh token is present but unused.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗