Axios interceptors for refreshing token

1k views Asked by At

I'm creating a react + Django application and I'm given an access token and a refresh token. The access token expires in 5 mins and refresh token in 24 hours. Axios interceptor checks if the status is 401(unauthorized), it attempts to refresh it. Now the question is, in my redux-thunk actions I've to check case for when the 'refresh token' is expired in all my action calls.

Here's my code for axios interceptor

import { url } from "./constants";

const axios = require("axios");
const axiosApiInstance = axios.create();

const refreshAccessToken = async () => {
  const token = localStorage.getItem("refreshToken");

  const res = await axios.post(
    `${url}/accounts/token/refresh/`, { refresh: token }
  );

  return res.data.access;
}

// Request interceptor for API calls
axiosApiInstance.interceptors.request.use(
  async (config) => {
    const token = localStorage.getItem("accessToken")
    config.headers = {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
      //check this if causes problems
      "Content-Type": "application/json",
    };
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

// Response interceptor for API calls
axiosApiInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  async function (error) {
    const originalRequest = error.config;
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      const access_token = await refreshAccessToken();
      localStorage.setItem("accessToken", access_token);
      axios.defaults.headers.common["Authorization"] = "Bearer " + access_token;
      return axiosApiInstance(originalRequest);
    }
    return Promise.reject(error);
  }
);

export default axiosApiInstance;

If the refresh token is expired I cant make the api call. But in my case I want to be able to call redux action to sign out if the refresh token is also expired. I'm doing this in all of my action calls

export const createVTP = (formProps, callback, id, template_type) => async (dispatch) => {
  const params = new URLSearchParams([
    ["template_type", template_type],
  ]);
  try {
    const res = await axiosApiInstance.post(
      `${url}/brokerage/${id}/trading/`,
      formProps,
      { params }
    );

    dispatch({
      type: CREATE_VTP_NONE,
      payload: res.data,
    });
    callback();
  } catch (err) {
    if (err?.response?.status === 401) {
      dispatch({
        type: AUTH_ERROR,
        payload: `Session expired. Please Sign in again`,
      });
    }
  }
};

Is there a better practice of achieving this? A lot of repetitive code

0

There are 0 answers