Refresh Tokens
Part of the Backend Developer Roadmap
In short
Short access tokens are safer, but nobody wants to log in every 15 minutes. A refresh token quietly fetches a fresh access token in the background, so users stay logged in for days.
A longer-lived token used to silently obtain a new short-lived access token, keeping users logged in without forcing frequent re-authentication or leaving long-lived tokens exposed.

Think of it like this
Season pass and daily wristband
At an amusement park, your season pass stays safe in your wallet. Each morning you show it at the desk and get a fresh wristband for the rides. Lose the wristband and it's useless by evening. The access token is the wristband; the refresh token is the season pass.
Watch it happen
Silent refresh with rotation
GET /orders (access)
1/6The app calls the API with its 15-minute access token.
The big ideas
What you need to know
Two tokens, two lifetimes
Access token: minutes, sent on every call. Refresh token: days or weeks, sent only to the refresh endpoint.
Track refresh tokens
Keep a hashed copy in the database, so you can revoke them on logout or password change.
Rotate on every use
Each refresh returns a new refresh token and retires the old one. Reuse of an old one signals theft.
Keep them away from scripts
On the web, put the refresh token in an HttpOnly, Secure cookie scoped to the refresh path.
See it in code
Walk through the code
1app.post("/auth/refresh", async (req, res) => {2 const presented = req.cookies.refresh_token;3 const record = await db.refreshTokens.findByHash(sha256(presented ?? ""));4 5 if (!record || record.expiresAt < new Date()) return res.sendStatus(401);6 if (record.usedAt) {7 await db.refreshTokens.revokeFamily(record.familyId);8 return res.sendStatus(401);9 }10 11 await db.refreshTokens.markUsed(record.id);12 const { accessToken, refreshToken } = await issuePair(record.userId, record.familyId);13 res.cookie("refresh_token", refreshToken, { httpOnly: true, secure: true, sameSite: "strict", path: "/auth/refresh" });14 res.json({ accessToken });15});1/4Read the refresh token from its cookie and find its hashed copy in the database.
req.cookies needs cookie-parser. sha256, issuePair and db are your own helpers; issuePair saves the new refresh token's hash.
Save yourself the pain
Common mistakes
Oops
Making access tokens last a week so you can skip refresh tokens.
Do this instead
A leaked week-long token can't be cancelled. Keep access tokens short and let refresh tokens handle long logins.
Oops
Storing refresh tokens in plain text in the database.
Do this instead
Store a hash, just like a password. A database leak then doesn't hand out working tokens.
Your mission
Build silent refresh
Quick check
Why rotate the refresh token on every use?
Go deeper
- 1Implement a refresh-token endpoint that issues a new access token.
- 2Learn why access tokens are kept short-lived and refresh tokens longer-lived.
- 3Implement refresh token rotation to limit damage if one is stolen.
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.