Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Axios interceptors for token refreshing and more than 2 async requests available
let isRefreshing = false;
let refreshSubscribers = [];
const instance = axios.create({
baseURL: Config.API_URL,
});
instance.interceptors.response.use(response => {
return response;
}, error => {
const { config, response: { status } } = error;
const originalRequest = config;
if (status === 498) {
if (!isRefreshing) {
isRefreshing = true;
refreshAccessToken()
.then(newToken => {
isRefreshing = false;
onRrefreshed(newToken);
});
}
const retryOrigReq = new Promise((resolve, reject) => {
subscribeTokenRefresh(token => {
// replace the expired token and retry
originalRequest.headers['Authorization'] = 'Bearer ' + token;
resolve(axios(originalRequest));
});
});
return retryOrigReq;
} else {
return Promise.reject(error);
}
});
subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb);
}
onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token));
}
@martinjeannot

This comment has been minimized.

Copy link

commented May 2, 2018

Not bad, although the refreshSubscribers array is never cleared so all pushed callbacks will run each time more than 2 async requests are made, also HTTP 498 is not widely used so I'd stick with the original 401, but otherwise it helped, thanks.

@FilipBartos

This comment has been minimized.

Copy link

commented May 22, 2018

Thank you for this gist. There is mine update using redux action for token refresh.

let isAlreadyFetchingAccessToken = false
let subscribers = []

function onAccessTokenFetched(access_token) {
  subscribers = subscribers.filter(callback => callback(access_token))
}

function addSubscriber(callback) {
  subscribers.push(callback)
}

axios.interceptors.response.use(function (response) {
  return response
}, function (error) {
  const { config, response: { status } } = error
  const originalRequest = config

  if (status === 401) {
    if (!isAlreadyFetchingAccessToken) {
      isAlreadyFetchingAccessToken = true
      store.dispatch(fetchAccessToken()).then((access_token) => {
        isAlreadyFetchingAccessToken = false
        onAccessTokenFetched(access_token)
      })
    }

    const retryOriginalRequest = new Promise((resolve) => {
      addSubscriber(access_token => {
        originalRequest.headers.Authorization = 'Bearer ' + access_token
        resolve(axios(originalRequest))
      })
    })
    return retryOriginalRequest
  }
  return Promise.reject(error)
})
@PauloRobertTlss

This comment has been minimized.

Copy link

commented May 25, 2018

Parabéns! 10000 start!

@Sagaryalioe

This comment has been minimized.

Copy link

commented May 25, 2018

It means in your refreshAccessToken() function, it will ask for new access_token again for the next async request even if the access_token is not expired. Am I Correct? Since you are providing new refresh_token for next async request.

@drakoniprincessa

This comment has been minimized.

Copy link

commented Jun 22, 2018

at line 43 should be something like
refreshSubscribers = [];

@suchy

This comment has been minimized.

Copy link

commented Sep 15, 2018

Hi! Could you share how did you access store from interceptors?

@ModPhoenix

This comment has been minimized.

Copy link

commented Sep 19, 2018

@alfonmga

This comment has been minimized.

@Flyrell

This comment has been minimized.

Copy link

commented Nov 23, 2018

Here's a small package I created for this one -> axios-auth-refresh.
I'd be more than glad to get your contributions, as it's pretty simple right now (it'd probably need to react on more status codes, queue the requests while the token obtaining process is running, etc.).

@marcelogarbin

This comment has been minimized.

Copy link

commented Dec 10, 2018

Thank you for this gist. There is mine update using redux action for token refresh.

let isAlreadyFetchingAccessToken = false
let subscribers = []

function onAccessTokenFetched(access_token) {
  subscribers = subscribers.filter(callback => callback(access_token))
}

function addSubscriber(callback) {
  subscribers.push(callback)
}

axios.interceptors.response.use(function (response) {
  return response
}, function (error) {
  const { config, response: { status } } = error
  const originalRequest = config

  if (status === 401) {
    if (!isAlreadyFetchingAccessToken) {
      isAlreadyFetchingAccessToken = true
      store.dispatch(fetchAccessToken()).then((access_token) => {
        isAlreadyFetchingAccessToken = false
        onAccessTokenFetched(access_token)
      })
    }

    const retryOriginalRequest = new Promise((resolve) => {
      addSubscriber(access_token => {
        originalRequest.headers.Authorization = 'Bearer ' + access_token
        resolve(axios(originalRequest))
      })
    })
    return retryOriginalRequest
  }
  return Promise.reject(error)
})

Hello,
I used this solution and it worked, but I do not quite understand what it actually does when it calls the promise of the constant "retryOriginalRequest".

Could someone explain me how the code works?

thank you

@huhaotian

This comment has been minimized.

Copy link

commented Dec 13, 2018

it works for me

thank you

@wrabit

This comment has been minimized.

Copy link

commented Jan 22, 2019

@marcelogarbin an axios interceptor should return a promise. He creates a promise retrying the original request and returns that. It's so you can use axios as intended, chaining .then() to carry out further actions.

@ognjetina

This comment has been minimized.

Copy link

commented Jan 24, 2019

you are the Jaguar mate :)

@akhrabrov

This comment has been minimized.

Copy link

commented Apr 5, 2019

Thank u man!
I'm writed simple example for works with cookie/session in node.js

https://gist.github.com/nzvtrk/ebf494441e36200312faf82ce89de9f2

@garyoo

This comment has been minimized.

Copy link

commented May 23, 2019

Thank you very much

@daitonaaa

This comment has been minimized.

Copy link

commented Jun 22, 2019

Thank you man!!

@bionicvapourboy

This comment has been minimized.

Copy link

commented Jul 1, 2019

Using this interceptor, with 5 concurrent requests, I get 3 times a new access_token, I missed something ?

@oceanicdev

This comment has been minimized.

Copy link

commented Aug 15, 2019

@bionicvapourboy you can try to use a mutex for a promise creation.
https://www.npmjs.com/package/async-mutex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.