Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Axios interceptors and asynchronous login

I'm implementing token authentication in my web app. My access token expires every N minutes and than a refresh token is used to log in and get a new access token.

I use Axios for all my API calls. I have an interceptor set up to intercept 401 responses.

axios.interceptors.response.use(undefined, function (err) {   if (err.status === 401 && err.config && !err.config.__isRetryRequest) {     serviceRefreshLogin(       getRefreshToken(),       success => { setTokens(success.access_token, success.refresh_token) },       error => { console.log('Refresh login error: ', error) }     )     err.config.__isRetryRequest = true     err.config.headers.Authorization = 'Bearer ' + getAccessToken()     return axios(err.config);   }   throw err }) 

Basically, as I intercept a 401 response, I want to do a login and than retry the original rejected request with the new tokens. My serviceRefreshLogin function calls setAccessToken() in its then block. But the problem is that the then block happens later than the getAccessToken() in the interceptor, so the retry happens with the old expired credentials.

getAccessToken() and getRefreshToken() simply return the existing tokens stored in the browser (they manage localStorage, cookies, etc).

How would I go about ensuring statements do not execute until a promise returns?

(Here's a corresponding issue on github: https://github.com/mzabriskie/axios/issues/266)

like image 301
Dmitry Shvedov Avatar asked Mar 09 '16 18:03

Dmitry Shvedov


People also ask

How do I know if my tokens are expired Axios?

common['Authorization'] = 'Bearer ' + access_token; return axiosApiInstance(originalRequest); } return Promise. reject(error); }); The response interceptor checks to see if the API returned a 403 status due to an expired token. If so, it calls a function to refresh the access token which it uses for its call.

What are interceptors in Javascript?

Interceptors are code blocks that you can use to preprocess or post-process HTTP calls, helping with global error handling, authentication, logging, and more.

What are interceptors in API?

Interceptor is an API gateway server built for accepting API requests from the client applications and routing them to the appropriate backend services. May it be a single service or multiple services to be called in a single API call, interceptor provides you with the necessary tools to control your API request flow.

What is the use of Axios interceptors?

Axios interceptors are functions that Axios calls for every request. You can use interceptors to transform the request before Axios sends it, or transform the response before Axios returns the response to your code. You can think of interceptors as Axios' equivalent to middleware in Express or Mongoose.


1 Answers

Just use another promise :D

axios.interceptors.response.use(undefined, function (err) {     return new Promise(function (resolve, reject) {         if (err.status === 401 && err.config && !err.config.__isRetryRequest) {             serviceRefreshLogin(                 getRefreshToken(),                 success => {                          setTokens(success.access_token, success.refresh_token)                          err.config.__isRetryRequest = true                         err.config.headers.Authorization = 'Bearer ' + getAccessToken();                         axios(err.config).then(resolve, reject);                 },                 error => {                      console.log('Refresh login error: ', error);                     reject(error);                  }             );         }         throw err;     }); }); 

If your enviroment doesn't suport promises use polyfill, for example https://github.com/stefanpenner/es6-promise

But, it may be better to rewrite getRefreshToken to return promise and then make code simpler

axios.interceptors.response.use(undefined, function (err) {          if (err.status === 401 && err.config && !err.config.__isRetryRequest) {             return getRefreshToken()             .then(function (success) {                 setTokens(success.access_token, success.refresh_token) ;                                    err.config.__isRetryRequest = true;                 err.config.headers.Authorization = 'Bearer ' + getAccessToken();                 return axios(err.config);             })             .catch(function (error) {                 console.log('Refresh login error: ', error);                 throw error;             });         }         throw err; }); 

Demo https://plnkr.co/edit/0ZLpc8jgKI18w4c0f905?p=preview

like image 56
ForceUser Avatar answered Oct 13 '22 07:10

ForceUser