0

I have an app which uses Rails and React. The AJAX in rails part works fine but I have some components in React which use AJAX and the error occurs in the AJAX requests through React components.

I get the following error:

2017-10-17T15:36:26.933083+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-
5be9f6839c5b] Started POST "/quiz_submissions" for 162.158.165.188 at 2017-10-17 15:36:26 +0000
2017-10-17T15:36:26.935109+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-
5be9f6839c5b] Processing by QuizSubmissionsController#create as JSON
2017-10-17T15:36:26.935151+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b]   Parameters: {"quiz_submission"=>{"quiz_problem_id"=>"21", "checked_option_ids"=>["88"]}}
2017-10-17T15:36:26.935688+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] Can't verify CSRF token authenticity.
2017-10-17T15:36:26.936459+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
2017-10-17T15:36:26.937451+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b]   
2017-10-17T15:36:26.937485+00:00 app[web.1]: [14b2fc9e-80b7-490f-b905-5be9f6839c5b] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

I've tried adding the CSRF Token in ajax header by adding this to my main.js

$.ajaxSetup({
  beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', 
  $('meta[name="csrf-token"]').attr('content'))},
});

This works completely fine on my local machine but gives the same error on production environment(Heroku).

Alternatively, I've also tried adding the CSRF Token in the header of individual ajax requests inside the React Component as follows:

$.ajax({
      dataType: 'JSON',
      type: 'POST',
      url: '/quiz_submissions',
      context: this,
      headers: {
          'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
      },
      data: {
        ...
        }
      }

This approach also works fine locally but gives the same Can't verify CSRF token authenticity. error on production.

I have <%= csrf_meta_tags %> on my head section and I also have //= require jquery_ujs on my application.js

Any idea why it doesn't work on production environment on Heroku?

Swojeet
  • 73
  • 1
  • 1
  • 7
  • Few things; First, Rails does some behind the scenes magic to automatically apply CSRF tokens to non-get requests. So you shouldn't need to do any of this. The fact that it's not working is a sign that the csrf tag on your application is not set correctly. I would guess this is a result of having an asyncronous login page (built with react, rather than a traditional HTML form), thus the CSRF tag is not set on login. You can fix this by manually updating the CSRF tag after login with the information received from the login post. – Jake Haller-Roby Oct 17 '17 at 17:46
  • I'm using devise for the login form. And I have other parts which use ajax (not within react component) and I don't get any `Can't verify CSRF token authenticity.` error on those non react ajax requests, so I don't think it could be a problem with the login page, could it? – Swojeet Oct 17 '17 at 17:58
  • Try this one => `https://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails#answer-43138944` – 7urkm3n Oct 17 '17 at 18:02
  • @7urkm3n I tried it with `beforeSend` and `headers` in both `.ajax` and `.ajaxSetup`. It works flawlessly on my local machine, no errors and the ajax request is successful. But after I deploy it to heroku, I get the same `Can't verify CSRF token authenticity.` on heroku logs. – Swojeet Oct 17 '17 at 18:17
  • @Swojeet what rails version do u use ? – 7urkm3n Oct 17 '17 at 19:26
  • I'm using 5.1.0 @7urkm3n – Swojeet Oct 18 '17 at 03:06

1 Answers1

0

Probably, This should work.

LINK HERE !!!


Use jquery.csrf (https://github.com/swordray/jquery.csrf).

  • Rails 5.1 or later

    $ yarn add jquery.csrf
    
    //= require jquery.csrf
    
  • Rails 5.0 or before

    source 'https://rails-assets.org' do
      gem 'rails-assets-jquery.csrf'
    end
    
    //= require jquery.csrf
    
  • Source code

    (function($) {
      $(document).ajaxSend(function(e, xhr, options) {
        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);
      });
    })(jQuery);
    

7urkm3n
  • 6,054
  • 4
  • 29
  • 46
  • Hey @7urkm3n, I added the `jquery.csrf` and the ajax works while I precompile my assets locally and push it to heroku. But if precompile assets on heroku it says: `Sprockets::FileNotFound: couldn't find file 'jquery.csrf' with type 'application/javascript'` I added nodejs buildpack to heroku before the ruby buildpack and the precompiling assets succeeds but then I get the same `Can't verify CSRF token authenticity.` error. – Swojeet Oct 29 '17 at 03:25
  • how did u install it locally ? – 7urkm3n Oct 29 '17 at 08:44
  • You mean `jquery.csrf`? I ran `yarn add jquery.csrf` and included `//= require jquery.csrf` in my `application.js`. And I removed the headers which had CSRF token on ajax requests and it worked locally and also on heroku but threw this error: `Sprockets::FileNotFound: couldn't find file 'jquery.csrf' with type 'application/javascript'` on precompiling assets on Heroku. – Swojeet Oct 30 '17 at 09:19