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
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