react_on_rails
react_on_rails copied to clipboard
How to refresh CSRF token?
I am using ReactOnRails.authenticityToken(); to get the CSRF token generated by csrf_meta_tags. The problem is that when I send first request, it works fine as the token is valid. Whenever I send any subsequent API request, it returns the previously invalidated CSRF token and therefore I get ActionController::InvalidAuthenticityToken. How can I refresh the CSRF token after each API request?
@Talha345 nothing has changed around this for many years. I think there is something specific to your app.
@justin808 Could be but do you have any suggestion on how to deal with this scenario. I will try to explain my specific scenario in detail:
- React SPA endpoint is triggered and component is mounted and
csrf_meta_tagsare added via the layout. - I use the CSRF token and execute a login API. On success response, I update the user in the SPA and therefore there is no page reload.
- Since the user is logged in, I show a link to Logout and upon clicking on it another API is triggered but of course the CSRF token is already invalidated and I get an error.
NOTE: In older versions of Rails, a single CSRF token was used for each session but since recent versions, we have a new CSRF token for each new request.
Solution for anyone having the same issue:
- Added a after_action method in ApplicationController:
after_action :add_csrf_token_to_json_request_header
private
def add_csrf_token_to_json_request_header
if request.format == :json && !request.get? && protect_against_forgery?
response.headers['X-CSRF-Token'] = form_authenticity_token
end
end
- On React side:
if (response.headers['x-csrf-token']) {
setAuthenticityToken(response.headers['x-csrf-token'])
}
export function setAuthenticityToken(token) {
const metaTag = document.querySelector("meta[name='csrf-token']");
metaTag.setAttribute('content', token)
}
Took inspiration from https://stackoverflow.com/questions/33941864/rails-automatically-update-csrf-token-for-repeat-json-request
@Talha345 @Judahmeek @alexeyr-ci Should this go into the docs? If so, could one of you submit a PR and I'll merge it.