OAuth

OAuth Refresh Token Expired โ€” How to Handle It

Updated April 2026

Reading this article? Verify your fix in real-time. Debug your OAuth error โ€” OAuthFixer โ†’

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

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

ProviderAccess tokenRefresh tokenIdle expiry
Auth024h (configurable)No expiry by default30 days idle
AWS Cognito1h30 days30 days from issue
Google1hNo expiry6 months unused
Microsoft/Azure1h90 days90 days idle
Okta1hConfigurableConfigurable

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