OAuth Refresh Token Expired — How to Handle It
A refresh token expires silently — your app keeps working until the next API call fails with invalid_grant or token_expired. Handle it gracefully: catch the error, clear tokens, redirect to login.
Why refresh tokens expire
- Inactivity timeout — providers expire refresh tokens after a period of no use (Auth0 default: 30 days, Cognito: 30 days, Google: 6 months)
- Token rotation — each refresh produces a new refresh token and invalidates the old one. Using an old token causes invalid_grant
- User revoked access — the user disconnected your app via provider settings
- Password changed — some providers revoke all tokens when a password changes
Catch expiry in your token refresh logic
async function getValidToken() {
const stored = getStoredTokens();
if (!stored) return promptLogin();
// Check if access token is still valid
if (Date.now() < stored.expires_at - 60000) {
return stored.access_token;
}
// Try to refresh
try {
const fresh = await refreshAccessToken(stored.refresh_token);
storeTokens(fresh);
return fresh.access_token;
} catch (err) {
if (err.error === 'invalid_grant' || err.status === 401) {
clearTokens();
promptLogin(); // redirect to /login
return null;
}
throw err; // re-throw other errors
}
}
Token lifetimes by provider
| Provider | Access token | Refresh token | Idle expiry |
|---|---|---|---|
| Auth0 | 24h (configurable) | No expiry by default | 30 days idle |
| AWS Cognito | 1h | 30 days | 30 days from issue |
| 1h | No expiry | 6 months unused | |
| Microsoft/Azure | 1h | 90 days | 90 days idle |
| Okta | 1h | Configurable | Configurable |
Silent re-authentication for SPAs
If you want to avoid visible login prompts, use silent auth — an invisible iframe that attempts to get a new token using a session cookie:
// Auth0 example — checkSession
auth0.checkSession({}, function(err, result) {
if (err) {
// Session expired — full login required
auth0.authorize();
} else {
// New tokens in result
updateTokens(result);
}
});
Debug your OAuth error live → OAuthFixer