JWT Refresh Tokens Explained
Learn how JWT refresh tokens work, why they pair with short-lived access tokens, rotation strategies, secure storage, and how to implement token refresh flows.
Detailed Explanation
A refresh token is a long-lived credential used to obtain new access tokens without requiring the user to re-authenticate. In JWT-based authentication systems, the combination of short-lived access tokens and longer-lived refresh tokens provides a balance between security and user experience.
The token pair pattern:
Login Response:
{
"access_token": "eyJhbGc...", // Short-lived (5-15 minutes)
"refresh_token": "dGhpcyBp...", // Long-lived (days to weeks)
"expires_in": 900
}
When the access token expires, the client sends the refresh token to a dedicated endpoint (e.g., POST /auth/token/refresh) to receive a new access token. This happens transparently to the user, maintaining their session without re-entering credentials.
Why not just use long-lived access tokens?
A long-lived access token that is stolen gives an attacker extended access. Short-lived access tokens limit the damage window to minutes. The refresh token is only sent to the auth server (not to resource APIs), reducing its exposure surface. If an access token is compromised, it expires quickly. If a refresh token is compromised, it can be revoked server-side.
Refresh token rotation:
Best practice is to implement refresh token rotation: each time a refresh token is used, the server issues a new refresh token and invalidates the old one. If an attacker steals and uses a refresh token, the legitimate user's next refresh attempt fails (because the old token was invalidated), signaling a potential breach. This is sometimes called "automatic reuse detection." The server should invalidate the entire refresh token family when reuse is detected.
Storage and security:
Refresh tokens should be stored securely. In browsers, HttpOnly cookies are preferred over localStorage because they are inaccessible to JavaScript, protecting against XSS attacks. In mobile apps, use secure storage mechanisms like iOS Keychain or Android Keystore. Refresh tokens should be bound to the client: the server records the client's fingerprint (IP, user-agent, or a device ID) and rejects refresh attempts from different contexts.
Server-side tracking:
Unlike access tokens, refresh tokens are typically stored in a database. This enables revocation, which is the key advantage of the refresh token pattern. When a user logs out, changes their password, or is deactivated, the server deletes their refresh tokens, preventing new access tokens from being issued.
Use Case
A mobile banking app uses 5-minute access tokens with 30-day refresh tokens, allowing users to stay logged in while ensuring stolen access tokens expire quickly.