JavaScript: Is set-cookie and response handling an atomic operation?

Viewed 83

I use the following pattern for stateless authentication with CSRF protection:

  1. Generate new JWT cookie for each handled request
  2. Generate new CSRF token for each handled request. Include it in the JWT token and in the response header
  3. Assert the CSRF token in the request header matches with the one in the JWT token

Client-side code extracts the CSRF token from each response and includes it in each request. The fresh token is stored in the browser session storage. I'm a bit concerned about the cookie and the token getting out of sync at the client side.

Considered the following simplified example

return axios.post(uri, payload, { headers: { 'X-CSRF-TOKEN': sessionStorage.getItem('X-CSRF-TOKEN') }})
    .then(response => sessionStorage.setItem('X-CSRF-TOKEN', response.headers['X-CSRF-TOKEN']))

Is the browser cookie update and response handling an atomic operation given JavaScript's event loop model? Or is it possible for other asynchronous XHR requests to use stale token value for the present cookie in the marginal time window?

1 Answers

The event loop model allows other code to run before the response => sessionStorage.setItem('X-CSRF-TOKEN', response.headers['X-CSRF-TOKEN']) is actually executed because this callback will be queued when receiving the HTTP response. Some other callbacks triggered either by a network event, a timer, or a user event on the page might have been queued meanwhile.

Your backend is supposed to return 403 when not receiving the CSRF token, so you could implement a "retry" logic to solve your problem.

Related