Token Rotation in MCP: Limiting the Blast Radius of Leaked Credentials

One leaked static MCP token can silently touch GitHub, AWS, Slack, and your database simultaneously - for months. Here's how token rotation shrinks that to minutes.

MK

Mohammed Kafeel

Machine Learning Researcher

June 22, 202613 min read
On this page

Last updated: June 2026

Imagine an AI agent quietly exfiltrating your company's source code. No alerts fire. No anomaly triggers. The agent is using a perfectly valid token - one that was leaked three months ago and has never expired.

Nearly 88% of MCP servers require authentication to external services, yet only 8.5% implement proper mechanisms for securing those credentials (Doppler, 2025).


What Is the "Blast Radius" of a Leaked Credential?

Blast radius is a security term borrowed from physical explosions: it describes the total damage a single compromised credential can cause before it's neutralized.

In MCP, the math is brutal. A single MCP server token often acts as a master key to your entire connected ecosystem:

  • Your GitHub repositories
  • Your PostgreSQL or RDS database
  • AWS S3 buckets and Lambda functions
  • Slack workspaces
  • Internal Jira or Confluence instances

That's five services from one credential. And because MCP agents operate autonomously, exfiltration can run silently for weeks.

Real scenario: An attacker compromises an MCP server token via phishing. The token has no expiry. Over 90 days, the attacker's script quietly reads pull requests, copies database schemas, and enumerates S3 buckets - all through legitimate API calls that look like normal agent traffic.


What Is Token Rotation and How Does It Work in MCP?

Token rotation means automatically replacing tokens at short intervals so that any leaked token expires before an attacker can weaponize it.

MCP authentication operates on two layers:

Layer 1: Client → MCP Server (OAuth 2.1)

The MCP spec mandates OAuth 2.1 with PKCE.

Layer 2: MCP Server → Backend Services (where 88% of the risk lives)

This is where most teams get it wrong. The MCP server needs credentials to call GitHub, AWS, Slack, your database. These are typically long-lived static tokens.

How the Token Lifecycle Works

Short-lived access tokens (15–60 minutes) - The access token is what the client presents on every request.

Refresh token rotation - When a client uses a refresh token to get a new access token, the authorization server (a separate entity from your MCP server - see resource vs auth server separation):

  1. Issues a new access token
  2. Issues a new refresh token
  3. Immediately invalidates the old refresh token

If an attacker steals a refresh token, using it triggers invalidation - and the legitimate client's next refresh attempt fails, alerting your system to the compromise.


Why Static Tokens Are a Ticking Time Bomb

Static Token Short-Lived (no rotation) Rotated Token
Lifespan Indefinite 15–60 minutes 15–60 min + rotated refresh
Blast radius if leaked Catastrophic Low Minimal
Revocation speed Manual, delayed Automatic on expiry Automatic + reuse detection
Implementation complexity Very low Medium Medium–High
Detects active compromise? ✅ Yes (refresh reuse alert)

The last row is the critical differentiator. Refresh token rotation is the only mechanism that actively signals a compromise.


How to Implement Token Rotation in MCP - Step by Step

Step 1: Adopt OAuth 2.1 with PKCE for Client-to-Server Auth

Non-negotiable for remote MCP. PKCE prevents authorization code interception. (For the full MCP OAuth 2.1 implementation, see our step-by-step PKCE guide.)

Step 2: Set Short Access Token TTLs

15–60 minutes maximum. Auto-refresh at ~80% of TTL. For background agents, 5–15 minutes is appropriate.

Step 3: Enable Refresh Token Rotation

Each use issues a new refresh token and invalidates the old. Most modern auth providers (Auth0, Okta, Keycloak, AWS Cognito) support this natively - it's usually a toggle.

async function refreshAccessToken(refreshToken: string): Promise<TokenSet> {
  const response = await fetch('https://auth.example.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: process.env.CLIENT_ID!,
    }),
  });

  if (!response.ok) {
    // Refresh token invalid or reused - possible compromise
    throw new Error(`Token refresh failed: ${response.status}`);
  }

  const tokens = await response.json();
  await secureStore.set('refresh_token', tokens.refresh_token);
  await secureStore.set('access_token', tokens.access_token);
  return tokens;
}

Step 4: Apply Least-Privilege Scopes

Never use catch-all scopes. repo:read instead of repo, s3:GetObject for a specific bucket instead of s3:*.

Step 5: Use Per-User / Per-Service Tokens

Never share org-wide static tokens. Each user, agent, or service gets its own token with its own scope.

Step 6: Store Tokens in OS-Native Secure Storage

  • macOS: Keychain Services
  • Windows: Windows Credential Manager
  • Linux: libsecret / GNOME Keyring
  • Cloud/Server: AWS Secrets Manager, HashiCorp Vault, Azure Key Vault

Never store in .env files, config files, or source code.

Step 7: Implement Token Introspection

Validate tokens server-side on every request. Token introspection (RFC 7662) lets your MCP server check whether a token is active even if it hasn't expired.

Step 8: Set Up Automatic Revocation

Trigger revocation on:

  • Session end or user logout
  • Anomaly detection
  • Employee offboarding
  • Detected refresh token reuse

What Happens When Token Rotation Isn't Enough?

Token rotation is powerful - but not a silver bullet. A real-world case from May 2026: researchers demonstrated a five-step attack on Claude Code (BankInfoSecurity) where attackers could silently redirect MCP traffic and intercept OAuth tokens. The attack persists after token rotation because the attacker's proxy intercepts new tokens as they're generated.

You also need:

  • Anomaly detection on token usage patterns - flag tokens from new IPs, unusual hours, abnormal resource access
  • Scope restriction - rotated token with repo:* still gives full repo access for 60 minutes
  • Session binding - tie tokens to client fingerprints (IP, device, user-agent)
  • Audit logging of all token issuance and use

The MCP specification's prohibition on token passthrough is also relevant - MCP servers must validate tokens directly, never forward them through intermediaries. (Token rotation is one line item in the full MCP security checklist.)


MCP-Specific Token Security Best Practices Checklist

  • OAuth 2.1 with PKCE implemented for all client-to-server auth
  • Access token TTL ≤ 60 minutes (15 minutes for background agents)
  • Refresh token rotation enabled - each use invalidates the previous
  • Least-privilege scopes - per-tool, per-resource, never catch-all
  • Per-user / per-service tokens - no shared org-wide credentials
  • Tokens stored in OS-native secure storage - not .env files
  • Token introspection implemented - server-side validation on every request
  • Automatic revocation on logout, session end, anomaly detection
  • Audit logs for all token issuance, refresh, revocation events
  • Anomaly detection on token usage patterns
  • Session binding - tokens tied to client fingerprints
  • Token passthrough prohibited - MCP server validates directly, never forwards

FAQ

What is token rotation in MCP?

The practice of automatically replacing authentication tokens at short intervals so that any leaked token expires before an attacker can cause significant damage. Operates at two levels: access token (15–60 minutes) and refresh token (invalidated on each use).

How does token rotation reduce the blast radius of a credential leak?

By limiting token validity. A static token leaked today might still be valid in six months. A rotated access token leaked today expires in 60 minutes. Refresh token rotation goes further: reuse actively signals compromise.

15–60 minutes for access tokens. For background agents, 5–15 minutes. Refresh tokens should be rotated on every use with no fixed TTL.

Does OAuth 2.1 require token rotation?

OAuth 2.1 makes PKCE mandatory and strongly recommends refresh token rotation. The MCP spec states token rotation should be implemented. For production, treat "should" as "must."

What's the difference between access token rotation and refresh token rotation?

Access token rotation issues new short-lived access tokens (the old simply expires). Refresh token rotation issues a new refresh token every time the old one is used and immediately invalidates the previous. Only refresh token rotation actively detects compromise.

Can token rotation prevent all MCP credential attacks?

No. The May 2026 Claude Code attack showed that an attacker with a proxy can intercept new tokens as they're generated. Token rotation must be combined with anomaly detection, scope restriction, session binding, and audit logging.

How do I store MCP tokens securely?

Use OS-native secure storage: Keychain (macOS), Windows Credential Manager, libsecret (Linux). For server-side, use AWS Secrets Manager, HashiCorp Vault, or Azure Key Vault. Never .env files or source code.

What should I do if an MCP token is compromised?

(1) Revoke the token at the authorization server immediately. (2) Revoke all tokens for that client if refresh token reuse is detected. (3) Audit the logs for all actions. (4) Rotate underlying credentials for backend services. (5) Notify affected parties. (6) Investigate the root cause.


Useful Sources