venkat g
venkat g

Reputation: 69

When using axios interceptors, API calls are looping for 401 error

I am trying to use interceptors in VueJs to request refresh token using axios. I have written some logic with interceptors and dispatch to store. When token expires and i reload the page, api post call is attempted infinitely forming a loop.to stop it i have to close the browser or logout and refresh the page. And the other error is "import/no-cylce" on my axios.js file when trying to import store. Below is my code, any suggestions are helpful, thanks.

axios.js


    import axios from 'axios';
    // eslint-disable-next-line import/no-cycle
    import store from '@/store';
    // eslint-disable-next-line import/no-cycle
    
    // axios.defaults.headers.common.Authorization = `Bearer ${sessionStorage.getItem('accessToken')}`;
    
    const getAPI = axios.create({
      baseURL: 'http://127.0.0.1:5000',
    });
    getAPI.interceptors.response.use(undefined, (error) => {
      if (error.config && error.response.status === 401) {
        const result = 'test interceptor';
        console.log(result);
        store.dispatch('refreshToken')
          // eslint-disable-next-line camelcase
          .then((access_token) => {
            axios.request({
              headers: { Authorization: `Bearer ${this.$store.state.accessToken}` },
            });
            console.log(access_token);
          });
      }
    });
    // eslint-disable-next-line import/prefer-default-export
    export { getAPI };

Below is Vuex store file, I created a refresh function to perform refresh.

import Vue from 'vue';
import Vuex from 'vuex';
// eslint-disable-next-line import/no-cycle
import { getAPI } from '@/axios';
// eslint-disable-next-line camelcase

Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    // accessToken: JSON.parse(localStorage.getItem('access_token')) || null,
    // refreshToken: JSON.parse(localStorage.getItem('refresh_token')) || null,
    accessToken: localStorage.getItem('access_token') || null,
    refreshToken: localStorage.getItem('refresh_token') || null,
    APIData: '',
  },
  getters: {
    loggedIn(state) {
      return state.accessToken != null;
    },
  },
  mutations: {
    // eslint-disable-next-line camelcase
    updateLocalStorage(state, { access_token, refresh_token }) {
      // localStorage.setItem('accessToken', JSON.stringify(access_token));
      // localStorage.setItem('refreshToken', JSON.stringify(refresh_token));
      localStorage.setItem('access_token', access_token);
      localStorage.setItem('refresh_token', refresh_token);
      // eslint-disable-next-line camelcase
      state.accessToken = access_token;
      // eslint-disable-next-line camelcase
      state.refreshToken = refresh_token;
    },
    // eslint-disable-next-line camelcase
    updateAccessToken(state, access_token) {
      // eslint-disable-next-line camelcase
      state.accessToken = access_token;
    },
    destroyToken(state) {
      state.accessToken = null;
      state.refreshToken = null;
    },
  },
  actions: {
    userLogin(context, credentials) {
      return new Promise((resolve, reject) => {
        getAPI.post('/login', {
          email: credentials.email,
          password: credentials.password,
        })
          .then((response) => {
            context.commit('updateLocalStorage', { access_token: response.data.access_token, refresh_token: response.data.refresh_token });
            resolve();
            console.log('\'access token\'', response.data.access_token);
            console.log('\'refresh token\'', response.data.refresh_token);
            // console.log(context.state.accessToken);
            // console.log(context.state.refreshToken);
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
    userLogout(context) {
      if (context.getters.loggedIn) {
        // context.commit('updateLocalStorage', null);
        context.commit('destroyToken');
      }
    },
    refreshToken(context) {
      return new Promise((resolve, reject) => {
        console.log(context.state.refreshToken);
        getAPI.post('/refresh', {
          // refresh_token: context.state.refreshToken,
          headers: { Authorization: `Bearer ${context.state.refreshToken}` },
        })
          .then((response) => {
            console.log('New access token granted');
            context.commit('updateAccessToken', response.data.access_token);
            console.log(context.state.accessToken);
            resolve(response.data.access_token);
          })
          .catch((error) => {
            console.log('\'error in refresh:\'', error);
            reject(error);
          });
      });
    },
  },
});

Below is view file for protected data. About.vue

 created() {
    getAPI.get('/userList', {
      // eslint-disable-next-line no-undef
      headers: { Authorization: `Bearer ${this.$store.state.accessToken}` },
    },
    console.log(`Bearer ${this.$store.state.accessToken}`))
      .then((response) => {
        this.$store.state.APIData = response.data;
        console.log(response.data);
      })
      .catch((error) => {
        console.log(error);
      });
  },

Upvotes: 0

Views: 1035

Answers (1)

Kaumadie Kariyawasam
Kaumadie Kariyawasam

Reputation: 1476

Also, i'm getting this error earlier. I used axiosAuth instead of axio

ex-:

 const getAPI = axiosAuth.create({
      baseURL: 'http://127.0.0.1:5000',
    });

Upvotes: 0

Related Questions