Access Token vs Refresh Token


In modern web and mobile applications, authentication is the first step, but maintaining a secure session is the real challenge. That’s where Access Tokens and Refresh Tokens come into play. Let's dive into what they are, how they work, and why they matter.
What is an Access Token?
An Access Token is a short-lived credential used to access protected resources like user profiles, dashboards, APIs, etc.
Issued by: Authorization server (e.g., OAuth provider, custom backend)
Format: Mostly JWT (JSON Web Token)
Validity: Typically 5 to 15 minutes
GET /user/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...
What is a Refresh Token?
A Refresh Token is a long-lived token used to obtain new access tokens when the old ones expire.
Never used to access resources directly
Stored securely (preferably in httpOnly cookies)
Lifespan: Hours, days, or even months
POST /auth/refresh-token
Body: { "refreshToken": "eyJhbGciOi..." }
Response: { "accessToken": "new_access_token_here" }
Difference Between Access Token and Refresh Token
Feature | Access Token | Refresh Token |
Purpose | Authorize API/resource access | Get a new access token |
Expiry | Short (minutes) | Long (days/months) |
Usage | Sent in headers for every call | Sent only when access token expires |
Storage (Frontend) | In-memory or localStorage | httpOnly cookie (preferred) |
Security Risk | Lower (short-lived) | Higher (must be protected well) |
Exposure Risk | Easy to rotate | Harder to revoke if stolen |
How They Work Together
✅ User logs in → gets Access Token & Refresh Token
⏳ Access Token expires after 15 minutes
🔁 App uses Refresh Token to get a new Access Token
🔐 Keeps session alive without asking user to log in again
When to Use What?
Scenario | Recommended Setup |
Public API (short session) | Access Token only |
SPA / React app | Access + Refresh Token |
Mobile app (e.g. Flutter) | Access + Refresh + Secure Storage |
Banking/Fintech | Short Access + Rotating Refresh |
Similarities
Both are issued after successful authentication
Both are signed (often using JWT)
Both can be revoked by backend
Both should be protected against XSS/CSRF
Token Flow Chart
Below is a simplified token lifecycle (shown in the uploaded chart):
Login → Token issued
Token sent with each request
If expired → refresh token used
New token issued → loop continues
Logout or refresh expiration → invalidate
Backend (Node.js + Express)
// Issue tokens
const accessToken = jwt.sign({ id: user._id }, "secret", { expiresIn: "15m" });
const refreshToken = jwt.sign({ id: user._id }, "refreshSecret", { expiresIn: "7d" });
Frontend (Axios Interceptor)
axios.interceptors.response.use(
res => res,
async error => {
if (error.response.status === 401) {
const res = await axios.post("/auth/refresh-token", { token: getRefreshToken() });
setAccessToken(res.data.accessToken);
return axios(error.config); // Retry original request
}
return Promise.reject(error);
}
);
Best Practices
🔒 Store Refresh Token in httpOnly cookies (not localStorage)
🔄 Rotate refresh tokens on every use
🧯 Revoke on logout
🔐 Use HTTPS always
✅ Implement token blacklist for compromised tokens
Real-World Applications
App | Token Usage |
Gmail | Uses both tokens for seamless auth |
GitHub | Short-lived access tokens for CLI sessions |
Spotify | Access token for playback, refresh for session renewal |
Firebase Auth | Uses access & refresh under the hood |
Access Tokens give you access.
Refresh Tokens help you keep it.
Together, they balance security and user experience.
If you're building modern apps — especially SPAs or mobile — understanding this duo is essential.
Subscribe to my newsletter
Read articles from Rohit Kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
