Why Refresh Tokens Exist
Access tokens are deliberately short-lived, often expiring in 5 to 60 minutes, to limit the damage a leaked token can cause. Forcing the resource owner to log in again every time an access token expires would be unusable, so the authorization server issues a longer-lived refresh token alongside the access token during the initial grant. The client stores the refresh token and, when the access token expires, silently exchanges it at the token endpoint for a fresh access token, without any browser redirect or user interaction, keeping the session alive while still bounding the blast radius of any single access token.
Cricket analogy: It's like a player's central contract with the BCCI: the match-day accreditation (access token) needs renewing every series, but the underlying contract (refresh token) means Rohit Sharma doesn't have to reapply for a new career every time one accreditation expires.
Refresh Token Rotation
In modern OAuth 2.0 deployments, especially for public clients like single-page apps and mobile apps, the authorization server rotates the refresh token on every use: each call to the token endpoint returns both a new access token and a new refresh token, and the old refresh token is immediately invalidated. This turns a stolen refresh token into a detectable event, since if both the legitimate client and an attacker ever try to use the same refresh token after one of them has already redeemed it, the second attempt fails, signaling token theft. Best practice ties this to automatic reuse detection: if a rotated-out refresh token is ever presented again, the authorization server should revoke the entire token family, not just the one request.
Cricket analogy: It's like a one-time toss coin used only once per match at the Eden Gardens: reusing yesterday's toss coin today immediately tips off the umpire that something's wrong, just as reusing an old refresh token flags theft.
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=v1.MzQ4YTk3ZjEtNGQ3YS05YzNlLTJmOGI1YTFlMGQ3Nw
&client_id=spa-web-client
// Response: both tokens rotate
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "v1.OTFiNC00ZDdhLTljM2UtMmY4YjVhMWUwZDc4",
"token_type": "Bearer",
"expires_in": 900
}
// The previous refresh_token is now invalid; reusing it
// triggers reuse detection and revokes the token family.Storage and Lifetime Considerations
Because a refresh token typically lives far longer than an access token, sometimes days or months, its storage location matters far more. Confidential clients running on a server can keep refresh tokens in a secure backend data store, but public clients like SPAs and native apps should combine rotation with sender-constraining techniques, or fall back to the Backend-for-Frontend pattern, keeping refresh tokens out of JavaScript-accessible storage entirely. Absolute and idle lifetimes should both be enforced: an absolute lifetime forces re-authentication after a fixed ceiling regardless of activity, while an idle lifetime expires a refresh token if it hasn't been used recently, limiting how long a stolen-but-unused token remains dangerous.
Cricket analogy: It's like the difference between a season-long stadium pass kept in a locked club safe (confidential client backend storage) versus a paper pass a fan carries loose in a pocket at the ground (SPA storage), which is far easier to lose or have pickpocketed.
Never store a long-lived refresh token in localStorage or a JavaScript-readable cookie for a browser-based app — any XSS vulnerability anywhere on the page grants an attacker a durable credential, not just a momentary one. Prefer HttpOnly, Secure, SameSite cookies managed by a backend-for-frontend.
- Refresh tokens let clients get new access tokens without redirecting the user back through login, keeping sessions alive while access tokens stay short-lived.
- Rotation issues a new refresh token on every use and invalidates the previous one, turning theft into a detectable, observable event.
- Reuse of an already-rotated refresh token should trigger revocation of the entire token family, not just rejection of that one request.
- Public clients (SPAs, native apps) need extra protection for refresh tokens: sender-constraining, rotation, or a Backend-for-Frontend pattern.
- Both absolute lifetimes (hard ceiling) and idle lifetimes (expiry after inactivity) should be enforced on refresh tokens.
- Refresh tokens should never live in localStorage or JS-readable cookies in a browser context, due to XSS exposure risk.
- Confidential clients can store refresh tokens server-side in a protected data store, which is inherently safer than any browser-accessible storage.
Practice what you learned
1. What is the primary security benefit of refresh token rotation?
2. What should an authorization server do if a refresh token that was already rotated out is presented again?
3. Why is storing a refresh token in a browser's localStorage particularly risky compared to storing an access token there?
4. What is the difference between an absolute lifetime and an idle lifetime for a refresh token?
5. Which pattern helps public clients like SPAs avoid holding long-lived refresh tokens directly in browser-accessible storage?
Was this page helpful?
You May Also Like
Access Tokens and JWTs
Access tokens are the credentials a client presents to a resource server, and JWTs are the most common self-contained format for encoding them.
Token Storage Best Practices
Where and how a client stores access and refresh tokens is often the deciding factor in whether an OAuth 2.0 integration is actually secure in practice.
Token Introspection and Revocation
Introspection lets a resource server ask the authorization server whether a token is still valid, and revocation lets a client or user proactively kill a token before it expires.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics