Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to refresh CSRF token? #1615

Open
Talha345 opened this issue May 9, 2024 · 4 comments
Open

How to refresh CSRF token? #1615

Talha345 opened this issue May 9, 2024 · 4 comments

Comments

@Talha345
Copy link

Talha345 commented May 9, 2024

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?

@justin808
Copy link
Member

@Talha345 nothing has changed around this for many years. I think there is something specific to your app.

@Talha345
Copy link
Author

Talha345 commented May 10, 2024

@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:

  1. React SPA endpoint is triggered and component is mounted and csrf_meta_tags are added via the layout.
  2. 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.
  3. 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.

@Talha345
Copy link
Author

Solution for anyone having the same issue:

  1. 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
  1. 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

@justin808
Copy link
Member

@Talha345 @Judahmeek @alexeyr-ci Should this go into the docs? If so, could one of you submit a PR and I'll merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants