[Bug] MCP OAuth refresh tokens stored but never used - causing widespread auth failures

Status Closed — duplicate
Maintainer reply None cached
Activity 3 comments · opened Jan 27, 2026 · closed Jan 31, 2026

Summary

Claude Code stores MCP OAuth refresh tokens but never uses them to refresh expired access tokens. This causes authentication failures requiring manual re-authentication, sometimes multiple times per day.

Evidence

Refresh tokens ARE stored

// From macOS Keychain - Claude Code-credentials
"supabase|...": {
  "accessToken": "sbp_oauth_...",
  "refreshToken": "UVemFCAEqbCNEpPqkG",  // ← Stored but never used
  "expiresAt": 1769635674007
}

MCP servers DO support refresh

Both Linear and Sentry OAuth metadata explicitly support refresh tokens:

// https://mcp.linear.app/.well-known/oauth-authorization-server
// https://mcp.sentry.dev/.well-known/oauth-authorization-server
"grant_types_supported": ["authorization_code", "refresh_token"]

Tokens expire with no refresh attempt

After ~24 hours (or less), tokens expire and users see:

  • "Invalid grant: refresh token is invalid"
  • MCP servers showing empty accessToken: "" and expiresAt: 0
  • Silent failures where MCP appears connected but returns "Unauthorized"

Impact

  • Atlassian Rovo MCP: "basically unusable after ~5 minutes" (see #5706)
  • Microsoft OAuth users: 60-90 minute token TTL = constant re-auth
  • Autonomous workflows: Fail mid-execution when tokens expire
  • Developer productivity: Multiple manual re-authentications per day

MCP Spec Compliance

The MCP Authorization spec states:

"Authorization servers SHOULD issue short-lived access tokens to reduce the impact of leaked tokens."

This implies clients MUST implement refresh token handling. Claude Code does not.

Related Issues (20+)

This is the root cause of many fragmented issues:

| Issue | Problem |
|-------|---------|
| #5706 | Original feature request (7+ months, no response) |
| #16957 | Exit-time refresh tokens not persisted |
| #19456 | Keychain permission errors on token update |
| #12447 | OAuth expiration disrupts autonomous workflows |
| #19481 | /mcp reconnect doesn't refresh expired tokens |
| #10784 | OAuth expiration causes retry storm (3.75M wasted tokens) |
| #18225 | Repeated 401 errors during active sessions |
| #10250 | OAuth succeeds but MCP reconnection fails |

Expected Behavior

  1. When access token expires, Claude Code should use stored refresh token
  2. On successful refresh, persist new access + refresh tokens
  3. On refresh failure, prompt user to re-authenticate (not fail silently)

Environment

  • Claude Code: 2.1.x (affects multiple versions)
  • Platform: macOS (also reported on Linux)
  • MCP servers affected: Linear, Sentry, Supabase, Atlassian, custom OAuth servers

---

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>

View original on GitHub ↗

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