Rails 5.0.0beta3: ActionController::InvalidAuthenticityToken in development
Asked Answered
C

2

5

I have just started a simple app with a couple of forms on Rails 5.0.0beta3.

In development, using http://localhost:3000 on Safari or Chrome to access the app, if I fill a form and submit it I always get an ActionController::InvalidAuthenticityToken error. However, if I reload the page before filling and submitting it then it works fine.

The app uses the defaults:

  • protect_from_forgery with: :exception in ApplicationController,
  • <%= csrf_meta_tags %> in html header through application layout,
  • development environment as created by rails.

Example:

<%= form_for @node, url: admin_book_nodes_url, as: :node do |form| %>
  <%= render "form", f: form %>
  <p><%= form.submit %> or <%= link_to "Cancel", admin_book_nodes_path %></p>
<% end %>

Log:

Started POST "/admin/book/nodes" for ::1 at 2016-03-20 11:54:31 +0000
Processing by Admin::Book::NodesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"/G5pF6hSPx0Vf21Fi0FCh+VlOcHY4w8C5lmHmwr3NQRjfXUP9/xboybeV3tevmyTyHcwSX8LplU/HgZVGDbGlw==", "node"=>{"parent_id"=>"1", "position"=>"1", "title"=>"lkjlkj", "description"=>"lkjlj", "published"=>"0", "content"=>"lkjlkj"}, "commit"=>"Create node"}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)

It works fine if I disable per form CSRF tokens in the controller (self.per_form_csrf_tokens = false) so my issue is really at that level.

The session does not seem to be reset at any point.

Interestingly, when the form is first loaded, the authenticity token in the header's menage tag is different from the token in the form. The meta tag is also at the bottom of the header's tags. When I then reload the tokens are the same in both the meta tag and the form, and the meta tag is at the top of the header's tags.

Update:

I think that the issue is down to Turbolinks.

When the form page is accessed from another page in the app, an XHR request is fired by Turbolinks, and I encounter the issue.

However, when I reload the page the browser reloads it and I don't see the issue.

Cleric answered 20/3, 2016 at 11:6 Comment(11)
Are your forms created with form_for and contain the correct CSRF inputs? There is used for normal syncrous form submissions. Are you using some sort of fragment caching that could deliver a "stale" CRSF meta tag?Nuisance
Are there any script errors in the browser console?Nuisance
Yes, forms created with form_for and contains the token (see update of my question). Caching is disabled in the default development environment. No errors in browser console.Cleric
Hmm, I wonder if it could be that the session is being reset on each request? That would cause a missmatch between the token on the server and what the user gets.Nuisance
Can you try reloading and check if the authenticity_token either the meta tag or the input stays the same? Also check if request.session_options[:id] remains constant.Nuisance
With self.per_form_csrf_tokens = false to be able to log in the action method, request.session_options[:id] seems to remain constant.Cleric
When I reload the page both tokens (meta data and form) change. What is interesting is that when I first load the page the meta data token is not the same as the one in the form. But after I reload they are both the same.Cleric
Experiencing the same issue: - meta csrf-token is different from form's authenticity_token when following a link from a page within the same site. OK when reloading the page.Recuperate
be sure to set a domain for your Rails.application.config.session_store :cookie_store in initializer/session_store. I was having problems with this because my session_store wasn't set correctly.Nudd
same here, but in my case the problem shows up only in production and only in chrome (firefox ok). there is an issue github.com/rails/rails/issues/21948 without solution yetDorcasdorcea
in my case the problem was with ssl and nginx config. forgery_protection_origin_check fails because request.origin != request.base_url (http vs https) because of wrong headers being passed from nginx github.com/rails/rails/issues/22965Dorcasdorcea
C
7

I have raised an issue on Rails.

After further investigation it seems that the issue is due to option :url in form_for.

See: Issue #24257 (not resolved yet)

Cleric answered 12/4, 2016 at 20:8 Comment(1)
In case it is helpful, a comment on that issue references a small note int he devise README regarding Rails 5: github.com/plataformatec/devise/pull/4033/files. This fixed my issues.Turnout
E
0

You can try run rails dev:cache as described here https://github.com/heartcombo/devise/issues/5273

I've also tried it and it has worked for me in three different machines, including a Windows WSL with Ubuntu 20.04.

I'm still trying to figure out the reason why it solves the issue, though.

Ebonyeboracum answered 6/10, 2020 at 3:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.