skip to Main Content

I would like to stop the infinite loop that I am getting with my axios interceptors.
When the user logs in, tokens are set in the local storage.
To test if token are being handled well, I change the value of the refresh token, and delete the access token, from the local storage.
When i do that, the user is suposed to be redirected to the login page, but it ends up in a infinite loop, unauthorized 401 error.

import axios from "axios";
import { logout } from "../stores/actions/authActions";
import store from "../stores";
import userEnv from "userEnv";
import { REFRESH_TOKEN_ENDPOINT } from "../constants/apiUrlConst";
import { ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY } from "../constants/tokenConst";

const axiosInstance = axios.create({
  baseURL: userEnv.apiUrl,
});

const refreshAccessToken = async () => {
  const refresh_token = localStorage.getItem(REFRESH_TOKEN_KEY);
  if (!refresh_token) {
    store.dispatch(logout());
    localStorage.clear();
    window.location.href = "/";
  } else {
    try {
      const response = await axiosInstance.get(REFRESH_TOKEN_ENDPOINT);
      const access_token = response.data.access_token;
      const new_refresh_token = response.data.refresh_token;
      localStorage.setItem(ACCESS_TOKEN_KEY, access_token);
      localStorage.setItem(REFRESH_TOKEN_KEY, new_refresh_token);
      return access_token;
    } catch (error) {
      return Promise.reject(error);
    }
  }
};

axiosInstance.interceptors.request.use(
  async (config) => {
    const url = config.url.toLowerCase();
    const method = config.method.toLowerCase();

    const token =
      url === REFRESH_TOKEN_ENDPOINT && method === "get"
        ? localStorage.getItem(REFRESH_TOKEN_KEY)
        : localStorage.getItem(ACCESS_TOKEN_KEY);
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

axiosInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    // 401 Unauthorized
    const originalRequest = error.config;
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        await refreshAccessToken();
        return axiosInstance(originalRequest);
      } catch (error) {
        return Promise.reject(error);
      }
    }
    return Promise.reject(error);
  }
);

export default axiosInstance;

Could anyone help me find whats causing this loop, and how do i stop it?

2

Answers


  1. One possible solution is to add a boolean flag to track if the refresh token has already been refreshed. this will prevent the interceptor from repeatedly retrying the request if it fails.

    const alreadyRefreshed = originalRequest._alreadyRefreshed;
    if (error.response?.status === 401 && !alreadyRefreshed) {
      originalRequest._alreadyRefreshed = true;
    

    by checking for this flag, the interceptor will only attempt to refresh the token once, preventing the infinite loop.

    Login or Signup to reply.
  2. If the above method didn’t worked, you can try adding a check for the error.response.data in the interceptor. Since refresh tokens can expire or become invalid, the 401 error may not always be caused by the need for a refreshed token. By checking the error response, it can determined if the 401 error is due to an invalid or expired refresh token, and only then attempt to refresh it.

    axiosInstance.interceptors.response.use(
      (response) => {
        return response;
      },
      async (error) => {
        // 401 Unauthorized
        const originalRequest = error.config;
        if (error.response?.status === 401 && !originalRequest._retry) {
          originalRequest._retry = true;
          try {
            await refreshAccessToken();
            return axiosInstance(originalRequest);
          } catch (error) {
          }
        }
      }
    );
    

    preventing the interceptor from continuously attempting to refresh the token for other types of 401 errors, such as expired access tokens.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search