Search code examples
reactjses6-promise

React - token refresh is being executed in wrong order


I'm quite new to React, and I've been helping to solve an issue in our project with React. The JWT token is expiring before some of the actions, and we need to refresh it using the JWT refresh token, before executing the "final" call we were going to execute originally.

Code would be similar to this one:

 mainFunction() {
    [...]
    if (!userTokenIsValid) {
       updateUserToken();
    }
    executeWhateverNeedsPermission();
    [...]
 }

 function userTokenIsValid() {
   if (!localStorage.userToken) return null;
   return (jwt.decode(localStorage.userToken).expiry > 30);
 }

 function getNewUserToken() {
   if (!localStorage.userToken) return null;
    return rp({
        uri: API_URL + "/token/refresh",
        method: 'POST',
        headers: {
            Authorization: localStorage.refreshToken
        },
        json: true
    }).then((data) => {
        if (!data || !data.userToken) {
            localStorage.removeItem('userToken')
        } else {
            localStorage.setItem('userToken', data.token);
        }
    }).catch((error) => {
        console.log("Something went wrong: " + error);
        throw error;
    });
 }

I'd be expecting the code above to be executed in order, so checking the token and requesting a new one if necessary, and then executing the request to the API.

But, in those cases where the token is expired, then I can see this order:

401 /admin/resources 200 /api/token/refresh

As said, I'm quite new to this, I think I should change the code to use promises, but every trial I gave didn't work (because of my newbie code, I must admit). Any help will be much appreciated!


Solution

  • I'm assuming you are calling getNewUserToken inside updateUserToken. With that code executeWhateverNeedsPermission is going to be called before the promise created by rp is completed. So you need to call executeWhateverNeedsPermission when the promise has been resolved. You can do something like this:

    function mainFunction() {
      // [...]
      if (!userTokenIsValid()) {
        updateUserToken().then(() => executeWhateverNeedsPermission());
      } else {
        executeWhateverNeedsPermission();
      }
      // [...]
    }
    

    Or improving the code a little using async/await:

    async function mainFunction() {
      // [...]
      if (!userTokenIsValid()) {
        await updateUserToken();
      }
      executeWhateverNeedsPermission();
      // [...]
    }