Seamless Authentication: Handling Token Expiry Without Re-Login

Published on 2026-02-16 16:30 by Frugle Me (Last updated: 2026-02-16 17:35)

#Token Expiry #Authentication #Auth
Share:

Seamless Authentication: Handling Token Expiry Without Re-Login

Nothing kills user retention like a "Session Expired" popup. To keep users engaged, you need a strategy that refreshes credentials silently in the background. Here is the industry-standard approach using Refresh Tokens and Axios Interceptors.

1. The Strategy: Dual Token System

Instead of one long-lived token, use two:
* Access Token: Short-lived (15–60 mins). Used for every API request.
* Refresh Token: Long-lived (7–30 days). Used only to get a new Access Token.

2. The Workflow

  1. The client sends an expired Access Token.
  2. The server returns a 401 Unauthorized error.
  3. The client "catches" this error, sends the Refresh Token to a /refresh endpoint.
  4. The server validates the Refresh Token and sends back a new Access Token.
  5. The client retries the original failed request with the new token.

3. Implementation (JavaScript/Axios)

This code uses an Axios Interceptor to automate the process so your UI components never even know a refresh happened.

```javascript
import axios from 'axios';

const api = axios.create({
baseURL: 'https://api.yourdomain.com',
});

// Request interceptor to attach the current token
api.interceptors.request.use((config) => {
const token = localStorage.getItem('access_token');
if (token) {
config.headers.Authorization = Bearer ${token};
}
return config;
});

// Response interceptor to handle 401 errors
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;

// If error is 401 and we haven't retried yet
if (error.response.status === 401 && !originalRequest._retry) {
  originalRequest._retry = true;

  try {
    const refreshToken = localStorage.getItem('refresh_token');

    // Call your refresh endpoint
    const res = await axios.post('https://api.yourdomain.com', {
      token: refreshToken
    });

    if (res.status === 200) {
      const { accessToken } = res.data;
      localStorage.setItem('access_token', accessToken);

      // Update the header and retry the original request
      originalRequest.headers.Authorization = `Bearer ${accessToken}`;
      return api(originalRequest);
    }
  } catch (refreshError) {
    // Refresh token is also expired/invalid -> Force Logout
    localStorage.clear();
    window.location.href = '/login';
    return Promise.reject(refreshError);
  }
}
return Promise.reject(error);

}
);

export default api;

Comments (0)

Want to join the conversation?

Please log in to add a comment.