Use axios to refresh access token

You should not allow a user to access resources that are protected; use must be authenticated.

One of the most common authentication mechanism is using Json Web Tokens.

Here is the flow,

  1. User logged int providing correct credentials
  2. Server authenticates and returns two tokens: access token, and refresh token
  3. Every time user makes a request, access token will be sent on the request header with header type Authorization followed by Bearer .i.e Bearer {accessToken}
  4. Server parses this token, validates it and allows the access

However, there is downside. If server issues a permanent token it will expose vulnerability i.e. token theft, or mis-use by other means.

To overcome this issue, it uses refresh token.

So, server generates access token with expiry less than a hour, or whatever is required as per the need. And, it generates refresh token with longer expiry.

What if access token expires?

  1. User makes a api call, server sends 401 as access token is expired
  2. User initiates a follow up api call to refresh token i.e. to get a new access token.
  3. If refresh token is expired, server sends again 401 and user must be logged out.

Now, how to automate these calls?

I will give an example to automate this with axios.

import axios from 'axios';
import LocalStorageService from './services/local-storage.service';
import refreshToken from './refresh-token';

const Client = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
});


// request interceptor to add token to request headers
Client.interceptors.request.use(
  async (config) => {
    const token = LocalStorageService.getAccessToken();
    if (token) {
      config.headers = {
        authorization: token,
      };
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// response interceptor intercepting 401 responses, refreshing token and retrying the request
Client.interceptors.response.use(
  (response) => response,
  (error) => {
    const { config } = error;
    if (error.response?.status === 401 && !config._retry) {
      config._retry = true;
      refreshToken(LocalStorageService.getRefreshToken())
        .then((res) => {
          const { accessToken } = res.data.data;
          LocalStorageService.setAccessToken(accessToken);
          return axios(config);
        })
        .catch((err) => {
          if (err.response.status === 401) {
            LocalStorageService.setUser(null);
            window.location.href = '/login';
          }
          return Promise.reject(err);
        });
    }
    return Promise.reject(error);
  }
);

export default Client;

Did you find this article valuable?

Support Sujeet Agrahari by becoming a sponsor. Any amount is appreciated!