1

My controller is responding to a js GET request, and in my js.erb file I am reporting back with the Fingerprint2 generated browser data of the users browser. This is done with a POST request, because of the large data string, so I have inserted a beforeSend method that adds the Authenticity Token.

However, this is rejected with ActionController::InvalidAuthenticityToken - ActionController::InvalidAuthenticityToken. When I check, the header looks like it does in the GET requests that succeed:

X-CSRF-Token:hl/TgkY7k0yBG03KX9IBrsDhk2K4tUUh8JTooT7A0yYZ0l53p8lTt0F3dZvRwyS3bIkbbkuTdElP2KisozjXjw==

The js code looks like this:

(new Fingerprint2).get(function(fingerprint, components) {
  return $.ajax({
    url: "/user_browser",
    type: "post",
    beforeSend: function(xhr) {
      xhr.setRequestHeader('X-CSRF-Token',
      $('meta[name="csrf-token"]').attr('content'))
    },
    data: {
      some_id: '123',
      components: JSON.stringify(components),
      fingerprint: fingerprint
    },
    dataType: "json"
  }).success(function(data) {});
});
Cjoerg
  • 1,271
  • 3
  • 21
  • 63
  • Just in case, are you sure you can just take csrf-token from the outside and use it, versus generating a new one for your request? [here](http://guides.rubyonrails.org/action_controller_overview.html#request-forgery-protection) it says "The form_authenticity_token generates a valid authentication token. That's useful in places where Rails does not add it automatically, like in custom Ajax calls." – Pavel Bulanov Jun 07 '16 at 11:23
  • I think I can just re-use the one generated in the `csrf-token` attribute. When I switch from `type: "post"` to `type: "get` there is no problem. – Cjoerg Jun 07 '16 at 12:48
  • As of get vs post, get requests are not verified for forgery protection. [here](https://github.com/rails/rails/blob/4-0-stable/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L190) – Pavel Bulanov Jun 07 '16 at 12:51
  • Ok, indeed you may use same csrf-token content within the user session. Unless you're using Rails 5 per_form_csrf_token, this should be the same token for all actions, incl. Ajax calls. Other q&a's on this topic mostly refer to the cashing issue, i.e. the token get cached (and e.g. belongs to other user). Are you able to manually submit a post request to the server with the given token to validate it? – Pavel Bulanov Jun 07 '16 at 15:00
  • As a hard method to debug, you may 1) encode your token using code from [here](https://github.com/rails/rails/blob/5-0-0/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L341) - e.g. like [this](https://repl.it/BwrP/12) and then 2) debug server code to find out session[:_csrf_token] value and compare manually – Pavel Bulanov Jun 07 '16 at 15:07

1 Answers1

0

I found the root of the problem. Some days ago I changed my config/session_store.rb from:

MyApp::Application.config.session_store :cookie_store, key: '_my-app_session'

to:

MyApp::Application.config.session_store :disabled

When I changed this back the problem disappeared.

Cjoerg
  • 1,271
  • 3
  • 21
  • 63