Modern web applications need a secure way to identify users after they log in. Whether you are building a React application, Node.js API, mobile app, or SaaS platform, authentication tokens are commonly used to maintain a user’s authenticated state.
Two important concepts in token-based authentication are access tokens and refresh tokens.
But what is the difference between them? Why do applications need both? How long should each token last? And which one should you store in cookies or local storage?
In this guide, we’ll explain access token vs refresh token, how they work together, their security differences, and common implementation patterns.
What Is an Access Token?
An access token is a credential that allows an authenticated user or application to access protected resources.
After a successful login, the authentication server typically issues an access token to the client.
For example:
User logs in
↓
Authentication Server
↓
Access Token
↓
Client Application
When the client wants to access a protected API, it sends the access token with the request.
A common approach is the Authorization header:
Authorization: Bearer ACCESS_TOKEN
The API validates the token and, if it is valid, allows the request.
Example
Suppose a user requests their profile:
GET /api/profile
Authorization: Bearer eyJhbGciOi...
The server verifies the access token before returning the user’s information.
How Long Does an Access Token Last?
Access tokens are generally designed to have a relatively short lifetime.
For example, an application might configure an access token to expire after:
- 5 minutes
- 15 minutes
- 30 minutes
- 1 hour
The exact lifetime depends on the application’s security requirements.
The reason for a short lifetime is simple: if an access token is stolen, the window in which it can be used is limited.
What Is a Refresh Token?
A refresh token is a longer-lived credential that allows a client to obtain a new access token after the current access token expires.
Instead of forcing the user to log in again every time the access token expires, the application can use the refresh token to request a new one.
The process looks like this:
Access Token Expires
↓
Client Sends Refresh Token
↓
Authentication Server
↓
New Access Token
↓
Client Continues Using API
Refresh tokens are therefore primarily used to maintain a user’s authenticated session without making the access token itself long-lived.
A refresh token might have a lifetime of days, weeks, or another period determined by the application’s security policy.
Access Token vs Refresh Token
The biggest difference between an access token and a refresh token is their purpose.
| Feature | Access Token | Refresh Token |
|---|---|---|
| Main purpose | Access protected resources | Obtain a new access token |
| Lifetime | Usually short-lived | Usually longer-lived |
| Sent to APIs | Yes | Usually no |
| Used frequently | Yes | Only when refreshing |
| Grants API access | Yes | Usually indirectly |
| Security impact if stolen | High | Potentially very high |
| Common storage approach | Memory or secure storage | Secure, preferably HttpOnly cookie |
| Can expire | Yes | Yes |
| Can be revoked | Depending on architecture | Commonly supported through server-side mechanisms |
The key idea is:
Access token = access the API
Refresh token = get a new access token
Why Do We Need Both Access and Refresh Tokens?
You might wonder why applications don’t simply use one long-lived access token.
The problem is security.
Imagine an access token remains valid for 30 days. If someone steals that token, they could potentially use it to access protected resources for the entire 30-day period.
Instead, applications can use:
Short-lived Access Token
+
Long-lived Refresh Token
This provides a better balance between security and user experience.
For example:
Access Token → 15 minutes
Refresh Token → Several days/weeks
When the access token expires, the application uses the refresh token to obtain a new access token.
The user can therefore remain logged in without keeping a powerful API credential valid for a long period.
How Access Tokens and Refresh Tokens Work Together
Let’s look at a typical authentication flow.
Step 1: User Logs In
The user submits their credentials:
POST /api/login
The server verifies the credentials.
Step 2: Server Issues Tokens
The server generates:
Access Token
Refresh Token
The client receives the authentication information according to the application’s chosen architecture.
Step 3: Client Calls the API
The client sends the access token:
GET /api/orders
Authorization: Bearer ACCESS_TOKEN
The API validates the token.
Step 4: Access Token Expires
Eventually, the access token becomes invalid.
The API may respond with:
401 Unauthorized
Step 5: Client Refreshes the Session
The client sends the refresh token to the token endpoint:
POST /api/auth/refresh
The authentication server validates the refresh token.
Step 6: Server Issues a New Access Token
If the refresh request is valid:
Refresh Token
↓
Authentication Server
↓
New Access Token
The application can continue making API requests without requiring the user to log in again.
Access Token vs Refresh Token: A Simple Example
Imagine you are building an online shopping application.
A user logs in at 10:00 AM.
The server issues:
Access Token → Expires at 10:15 AM
Refresh Token → Expires later according to the session policy
At 10:05 AM, the user requests their orders.
The access token is still valid.
At 10:20 AM, the access token has expired.
Instead of asking the user to log in again, the application sends a refresh request.
Expired Access Token
↓
Refresh Token
↓
New Access Token
↓
Request Orders
The user can continue using the application without noticing the token refresh process.
What Happens When an Access Token Expires?
When an access token expires, the API should reject requests that require it.
A common response is:
401 Unauthorized
The client can then attempt to obtain a new access token using the refresh token.
A simplified frontend flow might look like:
async function getProfile() {
const response = await fetch("/api/profile", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (response.status === 401) {
// Refresh access token
// Retry request
}
return response.json();
}
In production applications, token refresh logic is often centralized in an HTTP client or interceptor rather than repeated inside every API call.
Where Should Access Tokens Be Stored?
Token storage is an important security decision.
There isn’t one universal answer for every architecture, but common approaches include storing short-lived access tokens in memory and using secure cookies for refresh credentials.
Access Token in Memory
For browser applications, keeping the access token in memory can reduce persistence if the page is closed or reloaded.
The trade-off is that the token needs to be obtained again when the application starts a new session.
Access Token in Local Storage
Some applications store access tokens in local storage:
localStorage.setItem("accessToken", token);
This is convenient, but JavaScript can access local storage.
If an application has an XSS vulnerability, malicious JavaScript could potentially read the token.
For this reason, developers should carefully evaluate whether local storage is appropriate for authentication credentials.
Where Should Refresh Tokens Be Stored?
Refresh tokens are especially sensitive because they are usually longer-lived.
For browser-based applications, a common approach is to store the refresh token in a properly configured cookie.
For example:
HttpOnly
Secure
SameSite
An HttpOnly cookie cannot be accessed directly through JavaScript.
This can reduce the risk of token theft through certain XSS scenarios.
However, secure cookie configuration does not eliminate all security risks. Applications must also consider CSRF protection, session management, token rotation, logout behavior, and other security controls.
Access Token vs Refresh Token Security
Both tokens are sensitive, but their security roles are different.
Access Token
An access token typically:
- Has a short lifetime
- Is sent to protected APIs
- Provides access to protected resources
- Should be protected from theft
Refresh Token
A refresh token typically:
- Has a longer lifetime
- Is used to obtain new access tokens
- Should not normally be sent to every API endpoint
- Requires strong protection and lifecycle management
Because refresh tokens can remain valid longer, compromising one can be particularly serious.
What Is Refresh Token Rotation?
Refresh token rotation is a security technique where a refresh token is replaced with a new refresh token whenever it is used.
For example:
Refresh Token A
↓
Refresh Request
↓
New Access Token
+
Refresh Token B
The server can invalidate Refresh Token A after successful use.
This can help detect and limit certain replay attacks involving stolen refresh tokens.
A production authentication system should define clear rules for token rotation, reuse detection, expiration, and revocation.
What Happens If a Refresh Token Is Stolen?
A stolen refresh token can be more dangerous than a stolen short-lived access token because it may allow an attacker to obtain new access tokens.
That’s why refresh tokens should be protected carefully.
Security measures may include:
- Secure and HttpOnly cookies
- HTTPS
- Refresh token rotation
- Token expiration
- Token revocation
- Reuse detection
- Device or session tracking
- Strong logout and session invalidation mechanisms
The exact strategy depends on the authentication architecture and threat model.
Access Token vs Refresh Token in JWT Authentication
JWTs are often used as access tokens, although an access token does not have to be a JWT.
A JWT can contain claims such as:
{
"sub": "12345",
"role": "user",
"exp": 1787139000
}
The exp claim represents the token’s expiration time.
A server can verify the JWT before allowing access to a protected endpoint.
Refresh tokens can also be JWTs, but they don’t have to be. A server-generated opaque random value can be preferable in some architectures because it allows the server to maintain more direct control over refresh-token state and revocation.
Access Token vs Refresh Token in Node.js
A typical Node.js authentication architecture might look like:
Login
↓
Node.js API
↓
┌────────┴────────┐
↓ ↓
Access Token Refresh Token
↓ ↓
Protected APIs Refresh Endpoint
↓
New Access Token
For example, a protected API could validate the access token:
app.get("/api/profile", authenticateToken, (req, res) => {
res.json({
message: "Authenticated user",
});
});
A refresh endpoint could validate the refresh credential and issue a new access token:
app.post("/api/auth/refresh", refreshAccessToken);
The actual implementation should also include proper validation, expiration handling, revocation, error handling, and secure cookie configuration where applicable.
Access Token vs Refresh Token vs Session
These three concepts are related but different.
Session
A session represents the authenticated state of a user.
Access Token
An access token is a credential used to access protected resources.
Refresh Token
A refresh token is a credential used to obtain a new access token.
A simplified relationship is:
User Session
↓
Refresh Token
↓
Access Token
↓
Protected API
The exact architecture can vary depending on whether you’re using traditional server-side sessions, JWT-based authentication, OAuth 2.0, OpenID Connect, or another authentication system.
Common Mistakes Developers Make
1. Making Access Tokens Too Long-Lived
A very long access-token lifetime increases the potential impact of token theft.
2. Storing Sensitive Tokens Carelessly
Putting long-lived authentication credentials in JavaScript-accessible storage can increase the impact of an XSS vulnerability.
3. Not Expiring Refresh Tokens
Refresh tokens should have a defined lifecycle rather than being valid indefinitely.
4. Not Rotating Refresh Tokens
For applications that require stronger security, refresh token rotation can help reduce replay risks.
5. Sending Refresh Tokens to Every API
A refresh token should generally be restricted to the token-refresh mechanism rather than being sent with ordinary API requests.
6. Ignoring Logout
Logging out should invalidate or revoke the appropriate server-side session or refresh credential where the architecture supports it.
Which Is Better: Access Token or Refresh Token?
It’s not really a matter of choosing one over the other.
They solve different problems.
Access tokens are designed for accessing protected resources.
Refresh tokens are designed for maintaining authentication without requiring the user to repeatedly log in.
Using both can provide a useful balance:
Short-lived access
+
Longer-lived refresh
=
Better security + smoother user experience
The correct implementation depends on your application, authentication protocol, threat model, and security requirements.
Frequently Asked Questions
What is the difference between an access token and a refresh token?
An access token is used to access protected APIs and resources, while a refresh token is used to obtain a new access token after the current one expires.
Which token should expire first?
The access token should generally have a shorter lifetime than the refresh token.
Can a refresh token access an API directly?
Generally, refresh tokens should not be used as ordinary API access credentials. They are intended for obtaining new access tokens.
Should refresh tokens be stored in local storage?
For browser applications, storing long-lived refresh credentials in JavaScript-accessible local storage can increase exposure to XSS. A properly configured HttpOnly, Secure cookie is a common alternative.
Are access tokens and JWTs the same thing?
No. An access token describes the credential’s purpose, while JWT describes a token format. An access token can be a JWT, but it can also use another format.
What happens when an access token expires?
The API should reject the expired token. The client can then use a valid refresh mechanism to obtain a new access token.
Is a refresh token more secure than an access token?
Not necessarily. They have different purposes. Refresh tokens can be especially sensitive because they may be longer-lived and can be used to obtain new access tokens.
Conclusion
Understanding access token vs refresh token is essential when designing secure authentication for modern web and mobile applications.
The simplest way to remember the difference is:
Access Token → Used to access protected resources
Refresh Token → Used to obtain a new access token
Access tokens are typically short-lived and used frequently, while refresh tokens are longer-lived and used only when a new access token is required.
A well-designed authentication system should also consider secure token storage, expiration, refresh token rotation, revocation, HTTPS, XSS protection, CSRF protection, and proper logout behavior.
When implemented correctly, the combination of short-lived access tokens and carefully protected refresh tokens can provide a strong balance between security and user experience.




