In short
Short-lived access tokens are safer, but nobody wants to log in every 15 minutes. Refresh tokens quietly fetch a new one in the background, so users never notice.
A longer-lived token used to silently obtain a new access token once the short-lived one expires, avoiding forcing the user to log in again.

Think of it like this
Day pass and office ID card
At a big office, the guard gives you a visitor pass that expires by evening. Your long-term ID card stays in your wallet. When the pass expires, you show the ID at the desk and get a fresh pass, without the full check again.
Watch it happen
A silent refresh
GET /me (old token)
1/6The access token expired a minute ago, but the app doesn't know yet.
The big ideas
What you need to know
Two tokens, two lifetimes
The access token lives minutes and goes with every request. The refresh token lives days and is used only to get a new access token.
Keep the refresh token safe
Ideally it sits in an httpOnly cookie, which JavaScript can't read, so a script injected by an attacker can't steal it.
Refresh on 401
When a request fails with 401, call /auth/refresh, get a new access token, then retry the original request.
Only refresh once
If five requests fail together, share one refresh call instead of firing five.
See it in code
Walk through the code
1let refreshing: Promise<string> | null = null;2 3api.interceptors.response.use(undefined, async (error) => {4 const original = error.config;5 if (error.response?.status !== 401 || original._retried) throw error;6 original._retried = true;7 8 refreshing ??= api.post("/auth/refresh").then((r) => r.data.accessToken);9 const token = await refreshing.finally(() => (refreshing = null));10 11 original.headers.Authorization = `Bearer ${token}`;12 return api(original);13});1/4One shared promise, so many failed requests wait on a single refresh.
One shared refreshing promise means many failed calls wait on a single refresh. The _retried flag stops an endless loop if the new token also fails.
Save yourself the pain
Common mistakes
Oops
Retrying forever when the refresh endpoint itself returns 401.
Do this instead
Mark requests as retried once. If refresh fails, clear the session and send the user to login.
Oops
Storing the refresh token in localStorage next to the access token.
Do this instead
Prefer an httpOnly, Secure cookie set by the server, so page scripts can't read it.
Your mission
Simulate an expired token
Quick check
Why is the access token kept short-lived when a refresh token exists?
Go deeper
- 1Diagram the full flow: access token expires → refresh token exchanged → new access token issued.
- 2Learn why access tokens are kept short-lived and refresh tokens longer-lived.
- 3Trace through automatic token refresh via an Axios response interceptor.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.