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

getting "Can't verify CSRF token authenticity" even if csrf toke in present #2734

Closed
rtcoms opened this issue Nov 10, 2013 · 83 comments
Closed

Comments

@rtcoms
Copy link

rtcoms commented Nov 10, 2013

I'm doing simple authentication (without ajax or api) and getting error for csrf authenticity token. I'm using latest version of rails and devise

check the post request below

 Parameters: {"utf8"=>"✓",    
 "authenticity_token"=>"SJnGhXXUXjncnPhCdg3muV2GYCA8CX2LVFV78pqddD4=", "user"=> 
{"email"=>"a@a.com", "password"=>"[FILTERED]", "remember_me"=>"0"},
"commit"=>"Sign in"}

Can't verify CSRF token authenticity
 User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."email" =  
 'a@a.com' LIMIT 1
(0.1ms)  begin transaction
SQL (0.4ms)  UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?,
"sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 2  [["last_sign_in_at", Fri,
08 Nov 2013 14:13:56 UTC +00:00], ["current_sign_in_at", Fri, 08 Nov 2013 14:18:49 UTC
+00:00], ["sign_in_count", 3], ["updated_at", Fri, 08 Nov 2013 14:18:49 UTC +00:00]]
(143.6ms)  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 239ms (ActiveRecord: 144.5ms | Search: 0.0ms)
@josevalim
Copy link
Contributor

Can you please provide a sample application that reproduces the error?

@rtcoms
Copy link
Author

rtcoms commented Nov 10, 2013

here it is: (keep in mind that there are lots of gem which are not required but mentioned in Gemfile . This rep, I just keep updating to latest gems)

https://github.com/rtcoms/railsstarter

@latortuga
Copy link
Contributor

Your sample application is using an old version of devise. If you update it and are still seeing the error, we can take a look.

@rtcoms
Copy link
Author

rtcoms commented Nov 13, 2013

My bad. really sorry. I've updated the app with latest version of devise gem. Also added the devise secret key.

@kurko
Copy link

kurko commented Dec 1, 2013

I'm having this exact same problem in my app, but only in production, not in development/test env. I narrowed it down to this line:

# config/initializers/session_store.rb
Store::Application.config.session_store :cookie_store, key: '_some_key', domain: :all, tld_length: 2

With this line, sessions aren't destroyed anymore either.


@rtcoms I wasn't able to reproduce this problem in your sample app, neither in development nor in production (RAILS_ENV=production bundle exec rails server). Could you list exactly what you're doing to make it fail?

@rtcoms
Copy link
Author

rtcoms commented Dec 1, 2013

@everyone problem in my app is fixed. It was not related to devise . I removed 'rails-api' gem and it started working.

@kurko I removed some gems from my Gemfile .Try to have minimum no of gems in Gemfile and add extra gems one by one to find out which gem is causing error.

From my side this issue can be closed.

@lethjakman
Copy link

I have the same exact issue as kurko. Did you ever find a solution to your problem?

@kurko
Copy link

kurko commented Dec 13, 2013

Nope. I just disabled the feature for now, but I'll need it back soon. If you find the solution, please post it here.

@lethjakman
Copy link

Ok so I fixed my issue by changing the domain: to my domain name that I'm currently using. Turns out my dev domain didn't work with my production domain. I don't know if that'll help you but good luck!

@ctide
Copy link

ctide commented Feb 27, 2014

This isn't Devise related, as I'm running into the same problem after upgrading to Rails 4 without using the Devise gem at all. Commenting out the ':domain => :all, :tld_length => 2' section 'fixes' it, but we need that. Will try and figure out what the actual issue is and create an issue against Rails for it.

@lethjakman
Copy link

I actually found a better solution is to specify your :domain to your
actual domain name. I ran into other weird CSRF issues with :domain => all.

On Wed, Feb 26, 2014 at 7:22 PM, Chris Burkhart notifications@github.comwrote:

This isn't Devise related, as I'm running into the same problem after
upgrading to Rails 4 without using the Devise gem at all. Commenting out
the ':domain => :all, :tld_length => 2' section 'fixes' it, but we need
that. Will try and figure out what the actual issue is and create an issue
against Rails for it.

Reply to this email directly or view it on GitHubhttps://github.com//issues/2734#issuecomment-36203407
.

@coorasse
Copy link

I have the same problem.

I tried removing domain: :all and I don't have ruby-api gem.

I can reproduce the bug easily with my browser in Incognito Mode but only in production.

After digging a bit I did not find any solution so I just discarded the protection from sign_in form

@eiked
Copy link

eiked commented Apr 2, 2014

I had the same problem after switching to rails 4.

I store my session data in the database aka:
config.session_store :active_record_store

In my case the the session_id was not saved aka session_id=NULL

It was fixed by placing this in an initializer:
ActiveRecord::SessionStore::Session.attr_accessible :data, :session_id

(see rails/activerecord-session_store#6)

@lethjakman
Copy link

I fixed this issue a few times by pulling down a fresh copy of my repo from
get and starting from there. Something weird seemed to have been getting
cached that I couldn't find. Perhaps that could help one of you.

On Thu, Apr 3, 2014 at 4:21 PM, Joshua Kidd notifications@github.comwrote:

Yes... I too am having this same issue. I didn't have the rails-api gem, I
narrowed my gems down to just devise, and the problem only happens for some
browsers. In my chrome canary it will give error, in normal chrome it
works, in normal chrome incognito works, and in safari depending on what
computer I am on it will sometimes work or not work.

Reply to this email directly or view it on GitHubhttps://github.com//issues/2734#issuecomment-39512319
.

@vanboom
Copy link

vanboom commented May 1, 2014

I am seeing the same thing... Can't verify CSRF token authenticity in my application using Devise 3.2.4.

It seems to happen randomly, but is fairly repeatable shortly after restarting Apache... my app is deployed using Passenger on Apache.

Has anyone found a definitive bug?

@coorasse
Copy link

coorasse commented May 2, 2014

I didn't identified the bug and I'm still waiting for an answer. In the
meantime I just disabled forgery_protection for devise login form.

Alessandro Rodi

On Fri, May 2, 2014 at 1:47 AM, Don notifications@github.com wrote:

I am seeing the same thing... Can't verify CSRF token authenticity in my
application using Devise 3.2.4.

It seems to happen randomly, but is fairly repeatable shortly after
restarting Apache... my app is deployed using Passenger on Apache.

Has anyone found a definitive bug?


Reply to this email directly or view it on GitHubhttps://github.com//issues/2734#issuecomment-41969856
.

@ryanicle
Copy link

I am having the same issue as well. As @coorasse said, I disabled forgery_protection for now. Please share if anyone has found a fix. Thanks.

@coorasse
Copy link

Please reopen the issue or we'll have to create a duplicate

@josevalim
Copy link
Contributor

Folks, can someone please provide a way to reproduce the issue? It can even be in a new issue, as long as we link to this one. But we need a way to reproduce this, without a way to reproduce it, there is nothing we can do about getting it fixed.

@eiked
Copy link

eiked commented Jul 1, 2014

Hi Jose,

Did I report that?
Must not have been me.

~eike

Am 25.06.2014 um 16:08 schrieb José Valim notifications@github.com:

Folks, can someone please provide a way to reproduce the issue? It can even be in a new issue, as long as we link to this one. But we need a way to reproduce this, without a way to reproduce it, there is nothing we can do about getting it fixed.


Reply to this email directly or view it on GitHub.

@rience
Copy link

rience commented Jul 15, 2014

Just my 2c - my problem was that in session_store.rb I had

:secure => Rails.env.production?

and was not using SSL in production (still in development phase). So cookies were not sent => token was missing. Stupid mistake.

@Olgagr
Copy link

Olgagr commented Jul 21, 2014

We had the same issue. In session_store.rb we had these settings:

Rails.application.config.session_store :cookie_store, key: "_eqipia_session", domain: :all

We need it because we use subdomains on our staging and production environments and some of services like Xing do not allows us to setup oAuth callback for many subdomains (no * allowed).

Our client reported that he can't log in into admin panel. Client has access to both environments. The logs errors:

Started POST "/admin/sign_in" for 89.68.139.73 at 2014-07-21 10:37:31 +0000
Completed 422 Unprocessable Entity in 5ms
Processing by Auth::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NK1JAQUUAhm7Pi2aMdfepcOs6q90bi1Uqelq/Py6vi8=", "user"=>{"email"=>"admin@eqipia.com", "password"=>"[FILTERED]", "remember_me"=>"0"}}
Can't verify CSRF token authenticity
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
vendor/bundle/ruby/2.1.0/gems/actionpack-4.1.1/lib/action_controller/metal/request_forgery_protection.rb:176:in `handle_unverified_request'
vendor/bundle/ruby/2.1.0/gems/actionpack-4.1.1/lib/action_controller/metal/request_forgery_protection.rb:202:in `handle_unverified_request'
vendor/bundle/ruby/2.1.0/gems/devise-3.2.4/lib/devise/controllers/helpers.rb:182:in `handle_unverified_request'

After some research we figured out that the problem was only present in Chrome. Looking into Resources in Chrome console, I noticed we have the same cookies (one from stage environment and other for production), but of course with different values. It happens because I first logged in to production and then opened new tab and try to log in to staging. With these two cookies, the errors occurs.

eqipia_admin_panel

So in session_store.rb we change name for cookie into dynamic name:

Rails.application.config.session_store :cookie_store, key: "_eqipia_session_#{Rails.env}", domain: :all

This works, the cookies are not mixed up any more.

@locochris
Copy link

Yes, we had the same problem as @rience in our app.
ie. developing locally with RAILS_ENV=production, but with :secure => Rails.env.production? set in session_store.rb.
Next time if we want a more production-like version of our app running in a production environment we might try eg. ngrok-ing in over ssl.

@robinboening
Copy link

Had the same issue until adding an initializer that skips before action verify_authenticity_token.

@josevalim shouldn't this issue be opened again, or is it not related to devise?

@latortuga
Copy link
Contributor

Disabling verify_authenticity_token is a dangerous fix - it is putting out a fire by vacuuming up smoke. Please don't disable CSRF protection for your app.

If you have CSRF enabled and you see an authenticity token in the request, check that you actually have a session token in your cookies. Devise has exhaustive tests of this functionality - it is unlikely to be a devise issue.

@robinboening
Copy link

@latortuga: its not skipped for all requests in the app, but for our UserSessionsController that inherits from Devise::SessionsController only.

There always is an authenticity token in the request, but for some strange reasons I can not explain it can not be verified and the session is empty. Looks like the user was logged in, but the session is not written because of the not verified token. After this first failing login attempt, the next login just works... I dunno, its always the first attempt that is failing - always directly after a logout.

@latortuga
Copy link
Contributor

If the session is empty, obviously the token will not be verified - this is how CSRF protection in Rails works! Check if you're using httponly or secure flags for your sessions and that they match your desired configuration. If you watch your cookies when you visit the site and you don't see your app's session key (config/initializers/session_store.rb key config), then you don't have a token that can validate against the CSRF token server-side - this will cause the issue.

If you're not validating CSRF protection for login/logout, a malicious attacker could cause you to logout or login as someone else without your knowledge.

@talal7860
Copy link

This solved my problem

I overrode the devise sessions controller by creating a new file in controller/users/ with the name of sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
skip_before_filter :verify_authenticity_token, :only => [:destroy]
end

@danielbonnell
Copy link

I've tried every solution on here to no avail. I am running Rails 4.2 and the latest version of Devise on Heroku. My issue only seems to occur in Firefox and the environment doesn't matter. It happens both in development, test, and production. I can get around it in testing by stubbing the user login, but I can't seem to get around it in the other environments.

I can't figure out what caused the issue in the first place. I had no problems logging in through Firefox as recently as a week ago. I haven't pushed any new code up to the production app recently.

@unkrich
Copy link

unkrich commented Oct 27, 2016

I was able to solve this problem after quite a lot of troubleshooting. I am using cloudflare with heroku. The fix was to switch Cloudflare's SSL from Flexible to Full. Then everything worked. That simple.
Note that I am using the 'beta'-ish feature of Heroku's paid dynos which allow you to upload an SSL certificate for free rather than the SSL Endpoint plugin (if this matters).

@corps
Copy link

corps commented Nov 1, 2016

Another potential cause worth mentioning: sessions not saving. I had a problem in which my form was generating a csrf token, and it was being sent and received by the server correctly, but it was never matching the token in the session because a new one was being regenerated every request due to a session issue.

@santhoshdevadiga
Copy link

I have the same problem but I am not using the device.
In application controller added 'protect_from_forgery' to fix CSRF issue.

To reproduce
Step 1 : Login Page opened in 2 tabs (Tab1 and Tab2)
Step 2: From tab1 logged in and logged out
Step 3: From tab2 I tried to log in then I got below because token destroyed from tab1 logout request


Processing LoginController#login (for 70.71.248.213 at 2016-11-05 14:37:03) [POST]
  Parameters: {"authenticity_token"=>"sobCryvXTgoi29Ifwb88nJicHY+3jmiybWvXWwfghQw=", "commit"=>"Login", "controller"=>"login", "password"=>"[FILTERED]", "os_info"=>"Windows", "action"=>"login", "username"=>"test", "browser_info"=>"Mozilla an unknown version"}

ActionController::InvalidAuthenticityToken

The Same issue is happening for Ajax post request in another tab3 (opened another page before logout from tab1).

Do we have any solution to fix this issue?

@muhammadn
Copy link

muhammadn commented Jan 29, 2017

I have this problem (with Rails 5 and nginx) but proxy_set_header X-Forwarded-Ssl on; is a partial solution at least when i am using facebook OAuth login with Omniauth (and devise) with error like:

Can't verify CSRF token authenticity.

The solution is to use proxy_set_header X-Forwarded-Proto $scheme; instead of proxy_set_header X-Forwarded-Ssl on;

@rusllonrails
Copy link

@pdbradley thanks bro, your suggestion works perfect!

bluz71 pushed a commit to bluz71/platters that referenced this issue Feb 16, 2017
configuration.

Clearance/Devise authentication over HTTPS would fail without it due to
CSRF errors.

This issue explains it best:

  heartcombo/devise#2734
@paulewetzel
Copy link

Yep, proxy_set_header X-Forwarded-Proto $scheme; worked for me as well. I was just about to throw a TV out a 2nd story window, and now I can watch it instead....thanks!
location @Unicorn {
proxy_pass http://unicorn;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}

@janospapp
Copy link

Thank you guys! I've been struggling for days with authenticity token failure in chrome (in firefox it worked properly). After adding "proxy_set_header X-Forwarded-Proto $scheme;" to nginx config the problem is solved. I might messed up the config file when setting up ssl. Big thanks!!

@jarvisjohnson
Copy link

Following on from Cloudflare SSL comments above (@rdetert). If you are not using Heroku, so you aren't able to access an automatic SSL addon, you need to add an actual certificate on your nginx server manually.

Here's how I set it up on Digital Ocean:

Generate a TLS cert from cloudflare (free, just below the SSL flexible/full/strict area).

On the server (as root):

  • add the certs: {app_name}_cert.cert & {app_name}_key.key to /home/{your-app-name}
  • Change /etc/nginx/sites-available/{your-app-name} to include:
server {
        listen 80;
        listen 443;

        ssl     on;
        ssl_certificate         /home/{app_name}/{app_name}_cert.pem;
        ssl_certificate_key     /home/{app_name}/{app_name}_key.key;
        ...
}

Set Cloudflare SSL settings to Full(strict) to force Cloudflare to use your server certs

Finally, configure config/environments/production.rb : config.force_ssl = true

@Raja-Sharma
Copy link

Raja-Sharma commented Dec 27, 2017

Rails 5.1, aws elastic beanstalk with cloudfront.

Had the same error and tried everything here to no avail. Fixed it by changing cloudfront behavior settings. Set "Forward Cookies" to "all" from the default "none (Improves Caching)" in Distribution Settings > Behavior > (select behavior) > Edit.

@inem
Copy link

inem commented Jan 18, 2018

I recently caught the same problem.

This commit caused it:
image

Looks fine, but turns out it is a bad idea to access current_user in before_action in ApplicationController

Devise controllers are still controllers, and are inherited from ApplicationController.

So I tried to access current user in before_action, before devise finished its protect_from_forgery stuff.

The fix was to put protect_from_forgery before my action

@abpaul
Copy link

abpaul commented Apr 18, 2018

Faced this issue recently.
The error was appearing from the fact that one of our new layout files was a missing its csrf_meta_tags. So, for anyone else facing this issue, you might want to check there too! 😄

@lostphilosopher
Copy link

I had this problem, for me it was nothing to do with Devise. It was Rails5 + Heroku + CloudFlare as explained here: http://til.obiefernandez.com/posts/875a2a69af-cloudflare-flexible-ssl-mode-breaks-rails-5-csrf.

"Turn Cloudflare SSL to Full mode. Problem solved."

@czeisser
Copy link

I was experiencing this problem too. It turned out that the prepend: true option for protect_from_forgery was being overwritten.
I was using a gem that also declared protect_from_forgery but without the prepend option so it defaulted to false. (In my case auto_session_timeout gem was the culprit.)
To fix this I moved my protect_from_forgery after the auto_session_timeout in the ApplicationController.

  class ApplicationController < ActionController::Base
  ...
  
  auto_session_timeout Rails.configuration.session_timeout_length
  
  #has to be after auto_session_timeout so that prepend will not be overwritten.
  protect_from_forgery with: :exception, prepend: true

@ruvaleev
Copy link

For me the problem was solved when wrote this in my application_controller.rb

class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
check_authorization :unless => :devise_controller?

Another order of strings above was the reason of exception. Hope it'll help somebody.

@GuanglinDu
Copy link

I ran across this problem after I switched back and forth between the development and production environment on the same machine with browser Firefox. The 2 data sets are quite different. It took me 2 days to find out that it was caused by the Firefox cache. After the cache was cleared, Rails (4.2.11.1 & Ruby 2.2.5) functions properly. The lesson learned: never mix up the development and production environment on the same machine.

@clst
Copy link

clst commented Jun 27, 2019

I also came across this problem. After verifying that it worked fine on all other machines I tried I got suspicious.

Turns out Server 2016's Internet Explorer needs to have the Rails site added to "Trusted Sites" then it magically starts working. I have not investigated further.

@cruznunez
Copy link

i came across the problem and had nothing to do with Devise. My solution was different than the ones here.

I have two modal forms. It seemed like the 1st one was working and the 2nd one wasn't. I checked the authenticity tokens on them and they are different per form. I grabbed the authenticity token from the metatag and made that the value of the authenticity token hidden field for the 2nd form.

Tried it and it fixed it. Here's the coffescript:

editNoteModal = ->
  $('[href="#edit-note"]').click ->
    # code

    modal = $ '#edit-note'

    # code
    # code
    # code

    token = $('meta[name="csrf-token"]').attr('content')
    authTokenField = modal.find '[name=authenticity_token]'
    authTokenField.val token

$(window).on 'turbolinks:load', editNoteModal

@camilova
Copy link

This error was the browser's cache for me. I was working on two different projects, and both were on localhost:3000. When I came back to the first project after work on the another, I could not log in any more due wrong verification token, then I looked on the Chrome resources and there was a coockie from the another project. I have removed the wrong cookie, but it did not work, then I delete all the data of the browser through its configuration menu, and all is working get!

Before my solution I tried with a private window, on wich all worked, so I came to the idea of the browser's cache, that finally was the solution.

@Arish-018
Copy link

The simplest solution for the problem is do standard things in your controller or you can directly put it into ApplicationController

class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
end

@schappim
Copy link

schappim commented Aug 11, 2022

I had gone from "CSRF was previously working on localhost and production" to throwing the ActionController:: InvalidAuthenticityToken (Can't verify CSRF token authenticity.) when using the tunnelling service ngrok.

If you are using subdomains (including ngrok which uses [yoursubdomain].[country].ngrok.io , make sure that you have updated your session store to have a tld_length that matches the length of your domains (in the case of [yoursubdomain].[country].ngrok.io the length should be 3).

Eg:

Rails.application.config.session_store :cookie_store, key: "_example_session", domain: :all, tld_length: 3

For more info see: https://github.com/heartcombo/devise/wiki/How-To:-Use-subdomains

@lapser
Copy link

lapser commented Mar 13, 2023

In my case I get the "Can't verify CSRF token authenticity" log message after Devise form submission when I use this code (also mentioned here) in app/controllers/application_controller.rb.

class ApplicationController < ActionController::Base
  def default_url_options
    { locale: I18n.locale }
  end
end

I have to submit Devise forms two times to get e.g. the user signed in or get error messages on front end. It also seems this happens randomly!

If I remove the above-mentioned code, Devise seems to work as expected.

Using Rails 7.0.4.2 and Devise 4.9.0

P.S.: Maybe this is being solved by #5567

@codeodor
Copy link
Contributor

I ran into this and it was due to me having embedded one form tag inside another so that the app was expecting one token but getting the other. The solution was to ensure I closed out the first form tag before opening the second.

@lapser
Copy link

lapser commented Mar 21, 2023

P.S.: Maybe this is being solved by #5567

I tryed the recent rails 7.0.4.3 branch from @carlosantoniodasilva (#5567) and the issue related to the "Can't verify CSRF token authenticity" while using default_url_options seems not be solved.

@carlosantoniodasilva
Copy link
Member

@lapser if you can create a reproducible app, feel free to open another issue and we can take a look. This seems very unlikely to be something Devise specific, but a combination of factors.

@lapser
Copy link

lapser commented Apr 16, 2023

If you are using forms and turbo-links, the issue can be solved by adding a :authenticity_token => true, like:

<%= form_for @your_model, :remote => true, :authenticity_token => true do |f| %>
<% end %>

The above works to avoid getting the "Can't verify CSRF token authenticity" message using rails 7.0.4.3 and devise 4.9.0 with Hotwire Turbo (without :remote => true). It's the same as adding <%= hidden_field_tag :authenticity_token, form_authenticity_token %> into your form, like this:

<%= form_for @your_model, url: ... do |f| %>
   <%= hidden_field_tag :authenticity_token, form_authenticity_token %>
<% end %>

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

No branches or pull requests