Vue resource interceptor to refresh JWT token

684 Views Asked by At

I am trying to write a vue-resource interceptor that refreshes the JWT access token, when it has expired. I assume that I need to have a post-request callback that checks for token expiration error (status == 401 in my case), and then calls the refresh endpoint and re-tries the initial request.

With the code below, the only problem I face is that the next() call after refreshing the token never happens, even though the refresh executes fine and new tokens are saved to the localStorage.

Vue.http.interceptors.push(function (request, next) {

    if (!request.headers.has('Authorization') && window.localStorage.access_token) {
        request.headers.set('Authorization', `Bearer ${window.localStorage.access_token}`);
    }

    next(function (response) {
        if (response.status === 401) {
            const refreshToken = localStorage.getItem('refresh_token');

            Vue.http.post('/api/v4/auth/refresh', null, {
                headers: {'Authorization': `Bearer ${refreshToken}`}
            }).then((response) => {
                localStorage.setItem('access_token', response.data.accessToken);
                localStorage.setItem('refresh_token', response.data.refreshToken);
            }).then(() => {
                next();
            });
        }
    });
})
1

There are 1 best solutions below

3
Igor Moraru On

I think the chaining of callbacks is not quite right. The second call to next should happen when the first call returns a promise, and should not depend on the logic applied to resolve the first promise, only on successful resolution of that promise.

Vue.http.interceptors.push(function (request, next) {

  if (!request.headers.has('Authorization') && window.localStorage.access_token) {
    request.headers.set('Authorization', `Bearer ${window.localStorage.access_token}`);
  }

  next(function (response) {
    if (response.status === 401) {
        const refreshToken = localStorage.getItem('refresh_token');

        return Vue.http.post('/api/v4/auth/refresh', null, {
            headers: {'Authorization': `Bearer ${refreshToken}`}
        }).then((response) => {
            localStorage.setItem('access_token', response.data.accessToken);
            localStorage.setItem('refresh_token', response.data.refreshToken);
        })
    }
    return Promise.resolve(response)
  }).then(() => {
     next(); // This is called whenever the first callback returns a promise
  });
})