ActionController::InvalidAuthenticityToken

Viewed 273722

Below is an error, caused by a form in my Rails application:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

This happens for every non-get request and, as you see, authenticity_token is there.

26 Answers

For me the cause of this issue under Rails 4 was a missing,

<%= csrf_meta_tags %>

Line in my main application layout. I had accidently deleted it when I rewrote my layout.

If this isn't in the main layout you will need it in any page that you want a CSRF token on.

ActionController::InvalidAuthenticityToken can also be caused by a misconfigured reverse proxy. This is the case if in the stack trace, you get a line looking like Request origin does not match request base_url.

When using a reverse proxy (such as nginx) as receiver for HTTPS request and transmitting the request unencrypted to the backend (such as the Rails app), the backend (more specifically: Rack) expects some headers with more information about the original client request in order to be able to apply various processing tasks and security measures.

More details are available here: https://github.com/rails/rails/issues/22965.

TL;DR: the solution is to add some headers:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}

Add

//= require rails-ujs 

in

\app\assets\javascripts\application.js

This happened to me when upgrading from Rails 4.0 to 4.2.

The 4.2 implementation of verified_request? looks at request.headers['X-CSRF-Token'], whereas the header my 4.0 app had been getting was X-XSRF-TOKEN. A quick fix in my ApplicationController was to add the function:

  def verify_authenticity_token
    request.headers['X-CSRF-Token'] ||= request.headers['X-XSRF-TOKEN']
    super
  end

I have checked the <%= csrf_meta_tags %> are present and clearing cookies in browser worked for me.

Following Chrome Lighthouse recommendations for a faster application load, I have asynced my Javascript:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

This broke everything and got that Token error for my remote forms. Removing async: true fixed the problem.

This answer is much more specific to Ruby on Rails, but hopefully it will help someone.

You need to include the CSRF token with every non-GET request. If you're used to using JQuery, Rails has a helper library called jquery-ujs that builds on top of it and adds some hidden functionality. One of the things it does is automatically includes the CSRF token in every ajax request. See here.

If you switch away from it like I did you might find yourself with an error. You can just submit the token manually or use another library to help scrape the token from the DOM. See this post for more detail.

For Development environment, I tried many of these attempts to fix this issue, in Rails 6. None of them helped. So if none of these suggestions worked for you, try below.

The only solution I found was to add a txt file into your /tmp folder.

In your app's root directory, either run:

touch tmp/caching-dev.txt

Or manually create a file by that name in your /tmp folder. Since this fixed it for me, I assume the root of the issue is a caching conflict.

Running rails dev:cache in my console fixed this for me! (Rails 6)

I think it might be something to do with Turbolinks, but CSRF only seems to work when local caching is enabled.

This happened to me when carrying out manual tests of the sign up process of my application (signing up/in with multiple users).

A very simple and pragmatic solution may be to do what I did, and use a different browser (or incognito if using chrome).

This was a much better solution in my case than disabling security features!!

I experienced a similar error in Rails 6. Having tried the solutions above, I did a form review and saw that I had used a <button>.....</button> HTML tag in my form instead of submitting through Rails

<%= form.submit %>
form helper. Changing to the form helper resolved the issue.

In rails 5, we need to add 2 lines of code

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception
Related