5

I use Larave+JWT and vue2 + vuex2 + axios

So when user logins I store auth token in vuex store. When the token expires I need to refresh it. In order to refresh it I need to send the same token to /refresh route, and get a new token. At least that's how I got it and actually it works.

The problem is that interceptor catches 401 responses and tries to refresh token, but what if, say, in my component I send many requests with expired token? Since ajax requests are async, the interceptor code runs many times. So I got many refresh requests. Once the initial token is refreshed it is not considered valid. When interceptor tries to refresh invalid token server responds with error and I redirect to login page.

Here is the code:

axios.interceptors.response.use((response) => {
  return response;
}, (error) => {
  const originalRequest = error.config;

  if (error.response.status === 401 && !originalRequest._retry) {
    originalRequest._retry = true

    axios.post('auth/refresh').then((response) => {
      let token = response.data.token

      store.dispatch('auth/setAuthToken', token)

      let authorizationHeader = `Bearer ${token}`

      axios.defaults.headers = { 'Authorization': authorizationHeader }
      originalRequest.headers['Authorization'] = authorizationHeader

      return axios(originalRequest)
    }, (error) => {
      store.dispatch('auth/clearAuthInfo')
      router.push({ name: 'login' })
    })
  }

  return Promise.reject(error);
});
Victor
  • 5,073
  • 15
  • 68
  • 120

1 Answers1

1

I think you'll have to change your approach on how you refresh your token. Leaders like Auth0 recommends proactive periodic refresh to solve this problem.

Here is a SO answer where they talk about it.

Set the token expiration to one week and refresh the token every time the user open the web application and every one hour. If a user doesn't open the application for more than a week, they will have to login again and this is acceptable web application UX.

Community
  • 1
  • 1
aks
  • 8,796
  • 11
  • 50
  • 78
  • Hm, do I get it right that before initializing vue application (by doing new Vue()) I need to wait till refresh token request finishes? I use vue webpack template for my app. So looks like I should use axios.post('/auth/refresh').then(initialize my app). – Victor Mar 29 '17 at 16:29
  • It will not matter as the call is async, just store the token in state also and do the normal flow when token arrives it will be there in the state. – aks Mar 29 '17 at 17:22
  • Well it matters as I understand it. I put refreshing token in main.js where I init my app. So imagine I refresh the page and in the component which is tied to the page I do some ajax requests. So eventually we have 1 refresh token request, and few other ajax requests which rely on old token. So there is some uncertainty. Actually it just didn't work for me, don't remember exactly the issue but when I push initializing my app in refresh token success callback it started working – Victor Mar 29 '17 at 17:31
  • I mean when we refresh token after page refresh for example, not when we refresh it in timer, say, each hour – Victor Mar 29 '17 at 17:35