Keeping users logged in securely is essential for any modern web app. One way to achieve this is with token rotation, a method that automatically refreshes expired access tokens using a refresh token, all without interrupting the user experience. In this beginner-friendly guide, you'll learn how to implement token rotation in a React app using Axios interceptors, without interfering with your server logic. We'll also compare common token storage options so you can choose what's best for your project.
What is Token Rotation?
Token rotation is a technique where, instead of keeping a refresh token forever, you get a new refresh token each time you use it. This makes your app more secure because even if a refresh token is stolen, it can only be used once before it becomes invalid.
How Does Axios Interceptor Help?
Axios interceptors let you run logic before a request is sent or after a response is received. Here, we'll use a response interceptor to detect when an access token has expired and automatically fetch a new one using the refresh token-without the user noticing.
Step-by-Step Example: Token Rotation with Axios
Below is a simple implementation.
// api.js
import axios from 'axios';
// Create an Axios instance
const api = axios.create({
baseURL: 'https://your-api-url.com', // Replace with your backend URL
});
// Function to get tokens from storage
const getTokens = () => {
return {
accessToken: localStorage.getItem('accessToken'),
refreshToken: localStorage.getItem('refreshToken'),
};
};
// Function to save tokens to storage
const setTokens = ({ accessToken, refreshToken }) => {
localStorage.setItem('accessToken', accessToken);
if (refreshToken) localStorage.setItem('refreshToken', refreshToken);
};
// Add the access token to every request
api.interceptors.request.use((config) => {
const { accessToken } = getTokens();
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
});
// Handle token expiration and rotation
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// If the access token has expired, try to refresh
if (
error.response &&
error.response.status === 401 &&
!originalRequest._retry
) {
originalRequest._retry = true;
const { refreshToken } = getTokens();
if (refreshToken) {
try {
// Request new access token
const res = await axios.post('/auth/refresh', {
refreshToken,
});
// Save new tokens
setTokens(res.data);
// Retry the original request with new token
originalRequest.headers.Authorization = `Bearer ${res.data.accessToken}`;
return api(originalRequest);
} catch (refreshError) {
// Refresh token invalid, force logout or redirect to login
localStorage.clear();
window.location.href = '/login';
}
}
}
// Any other error
return Promise.reject(error);
}
);
export default api;
How it works:
Visual Flow
User clicks "Profile" →
Access token expired →
401 error →
Interceptor calls refresh endpoint →
Success? →
Retry original request →
User sees profile (no error)
Failure? →
Show login prompt (user sees error)
- Every request includes the access token.
- If the server returns 401 (Unauthorized), the interceptor tries to refresh the token using the refresh token.
- If successful, it retries the original request with the new access token.
- If refresh fails, it logs the user out.
Token Storage Options: Pros & Cons
Storage Option | Pros | Cons |
---|---|---|
Local Storage | Easy to use, persists after reload | Vulnerable to XSS attacks |
Session Storage | Safer than localStorage, cleared on tab close | Still vulnerable to XSS, not persistent |
HttpOnly Cookies | Protected from XSS, sent automatically | More complex setup, vulnerable to CSRF |
Summary:
- Local Storage: Simple, but less secure.
- Session Storage: Slightly safer, but data is lost on tab close.
- HttpOnly Cookies: Most secure, but requires backend changes and CSRF protection.
Conclusion
With Axios interceptors, you can easily implement token rotation in your React app. This keeps users logged in seamlessly and securely, without extra hassle. Remember to choose the token storage method that best fits your security needs and app requirements.
Thank you for reading, and have a beautiful day! ❤️
Top comments (0)