Refresh Token vs Access Token in Express Backend – Understanding the Differences

Introduction
Authentication is a critical aspect of web applications, ensuring that only authorized users can access protected resources. In an Express.js backend, authentication is commonly handled using JWT (JSON Web Token), which provides a secure way to verify user identity. Two types of tokens play a key role in this process: Access Tokens and Refresh Tokens. While both are essential for maintaining authentication, they serve different purposes. Let’s explore their differences and implementation in an Express.js backend.
What is an Access Token?
An Access Token is a short-lived token used to authenticate API requests. It is typically generated upon user login and included in request headers to access protected resources.
Characteristics of an Access Token:
Short lifespan (usually a few minutes to hours).
Sent with API requests in the
Authorization
header.Encodes user information (like user ID, role, etc.) in a compact and secure way.
Expires quickly, requiring re-authentication or refresh.
Example of Access Token Usage:
fetch('/api/protected-route', {
method: 'GET',
headers: {
'Authorization': `Bearer <access_token>`
}
});
What is a Refresh Token?
A Refresh Token is a long-lived token used to obtain a new access token when the current one expires. Instead of requiring the user to log in again, the refresh token helps maintain seamless authentication.
Characteristics of a Refresh Token:
Longer lifespan (can last days or weeks).
Stored securely (often in httpOnly cookies or a secure database).
Used only to obtain a new access token, not for direct API access.
Can be revoked if a user logs out or a security breach occurs.
Example of Refresh Token Usage:
fetch('/api/refresh-token', {
method: 'POST',
credentials: 'include'
})
.then(response => response.json())
.then(data => {
localStorage.setItem('access_token', data.accessToken);
});
Key Differences Between Access Token and Refresh Token
Feature | Access Token | Refresh Token |
Lifespan | Short-lived (minutes/hours) | Long-lived (days/weeks) |
Usage | Sent with API requests | Used to obtain a new access token |
Storage | Memory or localStorage | httpOnly cookies or database |
Security Risk | Higher if leaked | Less risky but still needs protection |
Implementing Access & Refresh Tokens in Express.js
1. Setting Up JWT Authentication
Install the required dependencies:
npm install express jsonwebtoken cookie-parser dotenv cors
2. Generating Access and Refresh Tokens
const jwt = require('jsonwebtoken');
const generateTokens = (user) => {
const accessToken = jwt.sign({ id: user.id }, process.env.ACCESS_TOKEN_SECRET, { expiresIn: '15m' });
const refreshToken = jwt.sign({ id: user.id }, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '7d' });
return { accessToken, refreshToken };
};
3. Protecting Routes with Access Tokens
const authenticateToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.status(401).json({ message: 'Access Denied' });
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err) return res.status(403).json({ message: 'Token Expired or Invalid' });
req.user = user;
next();
});
};
4. Handling Token Refreshing
const refreshTokens = []; // Store refresh tokens securely
app.post('/api/refresh-token', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken || !refreshTokens.includes(refreshToken)) return res.status(403).json({ message: 'Invalid refresh token' });
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if (err) return res.status(403).json({ message: 'Token Expired or Invalid' });
const { accessToken, refreshToken: newRefreshToken } = generateTokens(user);
res.json({ accessToken, refreshToken: newRefreshToken });
});
});
Security Best Practices
Use httpOnly and Secure cookies to store refresh tokens.
Set token expiration times to minimize security risks.
Implement token revocation when a user logs out.
Use HTTPS to encrypt tokens in transit.
Prevent XSS & CSRF attacks by sanitizing inputs and using CSRF protection.
Conclusion
Understanding the difference between access and refresh tokens is crucial for building a secure authentication system in Express.js. Access tokens provide quick authentication but expire fast, while refresh tokens help extend user sessions securely. By implementing both correctly, developers can enhance user experience while maintaining high security.
Subscribe to my newsletter
Read articles from paras jain directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
