Developer Guide · 2026
Access Tokens vs Refresh Tokens: Why One Dies in 15 Minutes and the Other Lives for 30 Days
Every modern auth flow uses two tokens with wildly different lifetimes. The access token dies in 5-15 minutes; the refresh token survives 7-30 days — and that asymmetry is deliberate. This guide explains why, how rotation and renewal work, and the mistakes that turn a solid design into a security hole.
Written by Benjamin Rotshtein
Updated
What is the difference between an access and a refresh token?
An access token is the short-lived credential a client sends with every API request. A refresh token is a long-lived credential kept secure and exchanged only at the token endpoint to mint new access tokens — usually issuing a fresh refresh token too. This split keeps the leaked-token blast radius to minutes while keeping users logged in.
Two tokens, one session: the division of labor
The access token is the workhorse: a JWT the client attaches to every request so an API can verify identity and permissions without a database lookup. The refresh token is the contract: a long-lived credential held securely by the client and exchanged only at the token endpoint. When the access token expires, the client trades the refresh token for a new access token — and usually a new refresh token too. That single exchange is what makes short access tokens usable.
Lifecycle: what actually expires and when
| Token | Typical lifetime | Where it goes | How expiry is enforced |
|---|---|---|---|
| Access token | 5-15 minutes | Every API request (Authorization header) | exp claim — stateless, checked per request |
| Refresh token | 7-30 days | Only to the token endpoint, when access expires | Stored server-side — revocable, not checked by APIs |
The access token’s exp claim is checked by every API on every request — stateless and instant. The refresh token’s expiry is checked only by the token endpoint, which also has the option to revoke it before it naturally expires. That contrast is the whole point: exposure is short, control is total.
Why 15 minutes? The blast-radius argument
Every API your app talks to receives the access token, so it is the token most likely to leak — in a log, a crash report, a compromised browser extension. If it lived for 24 hours, a single leak gives an attacker a full day of free access. At 15 minutes, the window is small enough that by the time the leak is noticed, the token is worthless. You shrink the access token not because renewing is free, but because a breach is expensive.
Why 7-30 days? Revocability is the safety net
The refresh token is long-lived only because it is protected. It never travels to arbitrary APIs, it is stored in a secure location (HttpOnly cookie or a secure client store), and — critically — the server can revoke it at any time: on logout, password change, or suspected compromise. A long-lived, revocable credential is safer than a short-lived, irrevocable one, because you can cut a stolen refresh token off instantly. That is why the refresh token, not the access token, defines the session length.
Refresh token rotation and reuse detection
Rotation: every time a refresh token is used, the endpoint issues a brand-new refresh token and invalidates the previous one. A token that was valid a minute ago is garbage a minute later. Reuse detection: if an already-rotated token shows up again, that means someone is replaying a stolen token — so the server revokes the entire session family and forces re-login. Together they turn token theft from a silent, indefinite compromise into a one-shot event that the server detects and kills.
When to renew: proactive, then reactive
Renewal should happen at two moments. Proactively: when an access token has under ~60 seconds of life left, refresh it in the background so a long-lived page never hits an unexpected 401. Reactively: when an API returns 401 for a token that may just be stale, retry once with a fresh token before surfacing an error. Everything else is either wasteful (renewing on every response) or broken (letting the user hit a failure you could have prevented).
const expiresIn = payload.exp - Math.floor(Date.now() / 1000);
if (expiresIn < 60) {
const { accessToken, refreshToken } = await tokenEndpoint(refreshToken);
// store the new access token; keep the rotated refresh token
}Six mistakes that break the model
- One token for both roles. Sending the same JWT as access and refresh token gives every API a credential that can mint new sessions.
- No rotation. A static refresh token lives until it expires — stolen once, usable for 30 days.
- Refresh token in localStorage. Any XSS reads it and takes over the session. Prefer an HttpOnly cookie.
- No reuse detection. Without it, a rotated token can be replayed silently; the server never notices.
- Renewing too eagerly. Hitting the token endpoint on every request defeats the purpose of a stateless access token and invites rate limits.
- Ignoring server clock skew. A refresh that mints an access token in the past (because of clock drift) produces tokens that fail immediately. Apply leeway on the validating side.
Verify your tokens actually say what you think
The fastest way to debug a confusing refresh flow is to decode the tokens themselves. A JWT decoder shows the exp, iat and jti claims of each token side by side — so you can confirm the access token really expires in 15 minutes and the refresh token really rotated, instead of guessing from the behavior of a black-box flow.
Frequently asked questions
What is the difference between an access token and a refresh token?
An access token is a short-lived JWT (typically 5-15 minutes) sent with every API request and verified statelessly by each service using its exp claim. A refresh token is a long-lived credential (typically 7-30 days) kept secure on the client and only sent to the token endpoint to mint the next access token. The refresh token is the source of truth for the session; the access token is just a fast pass.
Why are access tokens so short-lived (15 minutes)?
Because the access token is exposed to every API you call. If it leaks, an attacker can use it until it expires, so a short lifetime shrinks the blast radius to minutes. 15 minutes is a common default; 5 minutes for high-security systems. Long-lived access tokens (hours or days) only make sense when you cannot support refresh tokens and accept the larger leak risk.
How long should a refresh token live?
7-30 days is the common range, matched to your session requirement. A 7-day refresh token means users re-authenticate weekly; 30 days is typical for consumer apps with a 'remember me' flow. Because refresh tokens are stored server-side, you can revoke them instantly on logout or breach — which is exactly why the long lifetime is safe.
What is refresh token rotation and why does it matter?
Rotation means every time a refresh token is used, the token endpoint issues a new refresh token and invalidates the old one. Combined with reuse detection — if an already-rotated token is presented again, revoke the whole session — it defeats token replay attacks. A stolen refresh token then works at most once and trips an alarm.
When should my app actually renew the access token?
Two moments: proactively before expiry (when less than ~60 seconds remain, fetch a new access token in the background) and reactively on a 401 from an API. Never renew on every response and never wait until a user sees a failure for a request that could have been retried with a fresh token first.
Is it a security problem that access and refresh tokens have different lifetimes?
No — the asymmetry is the design. The short access token limits the damage of a leaked credential, while the long refresh token gives you a revocable session. The danger is the reverse pattern: a long-lived access token (24h+) that APIs blindly trust, because then a leak is both silent and long-lasting.
Check both tokens’ real expiry — 100% in your browser
Decode an access JWT and a refresh token and read their exp, iat and jti claims instantly, without the tokens ever leaving your machine. See exactly when each one dies.
Related guides
- JWT Refresh Tokens Explained: Expiration, Rotation & Security
Refresh token lifetimes, rotation, reuse detection, and keeping short-lived access tokens secure.
- JWT Expiration Time Explained: exp Claim, Timing & Common Pitfalls
How the exp claim works, why tokens look like they expire early, and how leeway absorbs clock drift.
- JWT vs Session: Which Authentication Should You Use?
Where token-based and session-based auth each win — and the decision rule for choosing between them.
- JWT Signature Verification: HS256 vs RS256, Explained with Code
How signature verification proves a token wasn’t tampered with, with working code examples.