Refresh Token

Authentication Security Notes Jan 6, 2025 JAVASCRIPT

Definition

A long-lived credential used to obtain new access tokens without requiring user re-authentication. Refresh tokens are issued alongside access tokens and are exchanged at the token endpoint for fresh access tokens when the current ones expire.

Example

After logging in, you receive an access token (expires in 15 minutes) and a refresh token (expires in 30 days). When the access token expires, your app uses the refresh token to get a new access token without asking the user to log in again.

Analogy

Like a seasonal pass to a theme park. Your daily ticket (access token) expires at the end of the day, but your seasonal pass (refresh token) lets you get a new daily ticket tomorrow without going through the purchase process again. If you lose the seasonal pass, you need to buy a new one.

Code Example


// Request refresh token during initial authorization
const tokenResponse = await fetch('https://oauth.provider.com/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: 'your_client_id',
    client_secret: 'your_client_secret',
    redirect_uri: 'https://yourapp.com/callback'
  })
});

const { access_token, refresh_token, expires_in } = await tokenResponse.json();

// Store refresh token securely
secureStorage.set('refresh_token', refresh_token);

// Use refresh token to get new access token
async function refreshAccessToken() {
  const response = await fetch('https://oauth.provider.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: secureStorage.get('refresh_token'),
      client_id: 'your_client_id',
      client_secret: 'your_client_secret'
    })
  });

  const tokens = await response.json();

  // Update stored tokens (some providers rotate refresh tokens)
  if (tokens.refresh_token) {
    secureStorage.set('refresh_token', tokens.refresh_token);
  }

  return tokens.access_token;
}

// Automatic token refresh on 401
async function apiCall(url) {
  let response = await fetch(url, {
    headers: { 'Authorization': `Bearer ${currentAccessToken}` }
  });

  if (response.status === 401) {
    currentAccessToken = await refreshAccessToken();
    response = await fetch(url, {
      headers: { 'Authorization': `Bearer ${currentAccessToken}` }
    });
  }

  return response;
}

Diagram

sequenceDiagram
    participant Client
    participant AuthServer as Auth Server
    participant API

    Note over Client,AuthServer: Initial Authentication
    Client->>AuthServer: 1. Login (credentials)
    AuthServer->>Client: 2. Access Token (15 min) + Refresh Token (30 days)

    Note over Client: Store both tokens securely

    Client->>API: 3. API call + Access Token
    API->>Client: 4. Response OK

    Note over Client,API: Time passes... Access token expires

    Client->>API: 5. API call + Expired Access Token
    API->>Client: 6. 401 Unauthorized

    Note over Client,AuthServer: Token Refresh Flow
    Client->>AuthServer: 7. Refresh Token
    AuthServer->>AuthServer: Validate refresh token
    AuthServer->>AuthServer: Rotate: invalidate old, create new
    AuthServer->>Client: 8. New Access Token + New Refresh Token

    Client->>API: 9. API call + New Access Token
    API->>Client: 10. Response OK

Security Notes

SECURITY NOTES

CRITICAL: Refresh tokens grant new access tokens. Require strict security and rotation.

Token Lifecycle:

  • Short-lived access token: 15 minutes to 1 hour
  • Long-lived refresh token: Days to months
  • Refresh endpoint: Endpoint to obtain new access token
  • Rotation: Issue new refresh token on each use
  • Revocation: Endpoint to revoke refresh tokens

Security:

  • Secure storage: Store refresh tokens securely (httpOnly cookies)
  • HTTPS only: Always transmit over HTTPS
  • Token rotation: Rotate on each use (prevents sharing)
  • Binding: Bind tokens to client credentials
  • Timeout: Expire refresh tokens after inactivity

Refresh Endpoint:

  • Authentication: Verify client identity
  • Validation: Validate refresh token hasn’t expired
  • Rate limiting: Limit refresh requests
  • Response: Return new access token (and optionally new refresh token)

Common Patterns:

  • Sliding window: New token before current expires
  • Token families: Track token generation families for reuse detection
  • Offline tokens: Special tokens for offline access
  • Refresh rotation: New refresh token with each access token

Revocation:

  • Logout: Revoke refresh token on logout
  • Security: Revoke if credentials compromised
  • Time limit: Revoke after max time regardless of use
  • Inactivity: Revoke if not used within time period

Standards & RFCs