heartcombo / devise

Flexible authentication solution for Rails with Warden.
http://blog.plataformatec.com.br/tag/devise/
MIT License
24k stars 5.55k forks source link

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

Closed rtcoms closed 10 years ago

rtcoms commented 11 years ago

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 commented 11 years ago

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

rtcoms commented 11 years ago

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 commented 11 years ago

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 commented 11 years ago

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

kurko commented 10 years ago

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 commented 10 years ago

@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 commented 10 years ago

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

kurko commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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/plataformatec/devise/issues/2734#issuecomment-36203407 .

coorasse commented 10 years ago

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 commented 10 years ago

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 https://github.com/rails/activerecord-session_store/issues/6)

lethjakman commented 10 years ago

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/plataformatec/devise/issues/2734#issuecomment-39512319 .

vanboom commented 10 years ago

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 commented 10 years ago

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/plataformatec/devise/issues/2734#issuecomment-41969856 .

ryanicle commented 10 years ago

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 commented 10 years ago

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

josevalim commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 10 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

@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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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.

talal7860 commented 9 years ago

Make sure that your csrf tag are being displayed as it should in firefox, this solved my problem, I accidentally deleted the csrf tags

On Sunday, April 5, 2015, Daniel Bonnell <notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com');> wrote:

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.

— Reply to this email directly or view it on GitHub https://github.com/plataformatec/devise/issues/2734#issuecomment-89655905 .

Thanks & Regards, Talal Arshad

danielbonnell commented 9 years ago

I had thought of that, but the CSRF tags are present in the DOM. Turns out the issue (at least for me) was being caused by the Blur / DoNotTrackPlus extension for Firefox. I had previously disabled it, along with my other extensions, but that had no effect. When I removed it, however, the problem went away. I further confirmed that by having a friend test the site on his machine using Firefox (without the extension).

Hope this helps someone in the future.

pankajp20 commented 9 years ago

I'm getting same error while updating a record on IE only. This do not happen application wide but occur for specific action of a controller. While submitting a form (action is used to update a record in DB), received error "Can't verify CSRF token authenticity". When checked form in IE, creates hidden field for "authenticity_token" but submitting the form redirect me to root URL of app (in application controller) and gives same error in console. Also form in IE contains "csrf_meta_tags".

I tried to skip validating the CSRF token authenticity for this specific action but then form's data is not submitted (write skip_before_action :verify_authenticity_token, only: [:] in my controller).

This problem is coming after app migrated from Rails 3.2 to 4.2 (Devise version 3.4). Any one have idea on this issue.

latortuga commented 9 years ago

I know this can be frustrating but it isn't helpful to bump this thread saying that you're experiencing this bug without a reproducible test case. If you have a sample application that exhibits the behavior, we can look at it and try to fix it. A good bug report will include 1. what went wrong 2. what you tried to fix it and 3. a way to reproduce the error.

talal7860 commented 9 years ago

And please try devise by installing it on a fresh install of rails with the same versions. You will figure out what are you doing wrong

On Monday, April 6, 2015, Drew Ulmer notifications@github.com wrote:

I know this can be frustrating but it isn't helpful to bump this thread saying that you're experiencing this bug without a reproducible test case. If you have a sample application that exhibits the behavior, we can look at it and try to fix it. A good bug report will include 1. what went wrong 2. what you tried to fix it and 3. a way to reproduce the error.

— Reply to this email directly or view it on GitHub https://github.com/plataformatec/devise/issues/2734#issuecomment-90158302 .

Thanks & Regards, Talal Arshad

pankajp20 commented 9 years ago

Thank you @latortuga and @talal7860, but the actual problem was the "div"s. Structure of that page is based on "div" and one "div" (where the form lies) was placed inside table body mistakenly. And that "div" floats in the page causing this bug. Either no table should be used or the "div" should be inside a "td" tag.

Aleksandaar commented 9 years ago

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 %>
pdbradley commented 9 years ago

Had this issue only in production (heroku) and fixed it by removing the :domain => :all

Myapp::Application.config.session_store :cookie_store, key: '_myapp_session',:domain => :all

to

Myapp::Application.config.session_store :cookie_store, key: '_myapp_session'
mtozlu commented 9 years ago

Make sure the browser you use accepts cookies (you can do it in settings). You can suspect this is the problem if the error happens in specific browsers (eg. Firefox).

david-meza commented 9 years ago

I had this issue only on heroku as well. Removing domain: :all worked for me

antonkoh commented 8 years ago

Having a similar problem on all browsers with my app: https://github.com/antonkoh/railsrep/tree/master/lesson17/my_app

First way to reproduce:

  1. As unauthorized user open any post on the main page.
  2. In another tab sign in (test00@test.com / 12345678)
  3. On the first tab, enter any symbols in the New Comment field and try to submit.

Second way to reproduce:

  1. As an authorized user (test00@test.com / 12345678) open any post on the main page.
  2. In another tab sign out.
  3. On the first tab try to add a comment.

Both ways end in ActionController::InvalidAuthenticityToken exception. This is also reproduced for any other POST requests from an unrefreshed page.

Devise 3.5.2, Rails 4.2.4

drewhamlett commented 8 years ago

Just in case anybody runs across this in Google(because I did). I used the domain: :all flag, and sign_out stopped working on production. I had two cookie sessions and I guess devise was only clearing one? Anyway removed domain: : all and everything is good again.

eddroid commented 8 years ago

I also resolved a similar Devise issue by unbundling the rails-api gem. Two different failures:

  1. authenticity_tokens generated by form_for were invalid on POST sessions#new.
  2. I had before_filter :authenticate_user! in ApplicationController. So there were no public pages (other than login). Even after a successful login POST, the session would remain empty and I'd be redirected to the login page again with a 401 Unauthorized.

Theory: rails-api (or something) is disabling the session, even in non ActionController:API-subclassed controllers. Since the token in the session needs to match the token in the form, token verification fails. The Rails source seems to indicate that if a session token comes back empty, a new random one is generated. This makes sense when rendering a form on a GET, but is unnecessary and confusing when handling POST/PUT/etc. The error isn't that the token doesn't match. The error is that, while your form has a token, the session doesn't, and your form's token doesn't match the one Rails just randomly generated.

allpumpedup commented 8 years ago

@drewhamlett suggestion of removing domain: :all flag worked for me.

adrianoresende commented 8 years ago

I have exactly the same of the first post problem, after switching to rails 5. It solves cases removing rails-api but It has included native for Rails 5 and how to solve? =(

Rails 5.0.0.beta3 Devise 4.0.0.rc2 (support for Rails 5)

My error:

Started POST "/admin/sign_in" for 127.0.0.1 at 2016-03-22 12:08:56 -0300
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"c2r8dL0baHl3NLUpW9s3fMoTcxuDaezGwSD2+2B4l7MHJJ0Hnwl4KTuowz1ewwSk6Hklqb/N+W40YJAa6YEBzw==", "user"=>{"email"=>"zullcore@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Entrar"}
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`email` = 'zullcore@gmail.com' ORDER BY `users`.`id` ASC LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.3ms)  UPDATE `users` SET `current_sign_in_at` = '2016-03-22 15:08:56', `sign_in_count` = 47, `updated_at` = '2016-03-22 15:08:56' WHERE `users`.`id` = 2
  SQL (0.4ms)  INSERT INTO `versions` (`item_type`, `item_id`, `event`, `object`, `created_at`, `object_changes`) VALUES ('User', 2, 'update', '---\nid: 2\nname: Adriano\nprofile: \nadmin: true\ncreated_at: 2016-03-21 23:51:39.000000000 Z\nupdated_at: 2016-03-22 15:08:49.000000000 Z\nemail: zullcore@gmail.com\nencrypted_password: \"$ ... \"\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 46\ncurrent_sign_in_at: 2016-03-22 15:08:49.000000000 Z\nlast_sign_in_at: 2016-03-22 15:08:49.000000000 Z\ncurrent_sign_in_ip: 127.0.0.1\nlast_sign_in_ip: 127.0.0.1\nphoto_file_name: \nphoto_content_type: \nphoto_file_size: \nphoto_updated_at: \ncreated_by: \nupdated_by: \n', '2016-03-22 15:08:56', '---\ncurrent_sign_in_at:\n- 2016-03-22 15:08:49.000000000 Z\n- 2016-03-22 15:08:56.000000000 Z\nsign_in_count:\n- 46\n- 47\nupdated_at:\n- 2016-03-22 15:08:49.000000000 Z\n- 2016-03-22 15:08:56.000000000 Z\n')
   (47.5ms)  COMMIT

Can't verify CSRF token authenticity

Redirected to http://localhost:3000/admin
Completed 302 Found in 186ms (ActiveRecord: 50.2ms)

Started GET "/admin" for 127.0.0.1 at 2016-03-22 12:08:56 -0300
Processing by Admin::PagesController#dashboard as HTML
Redirected to http://localhost:3000/admin/login
Filter chain halted as :require_login rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.0ms)
chris357 commented 8 years ago

Rails 4 on chrome.

Findings:

  1. Issue only occurs if user logs in, logs out, and then tries to log in again.
  2. Clearing the cache (shift + cmd + r) fixes the issues temporarily.

Is it possible that Angular continues providing the old CSRF token instead of a new one and this causes the issue?

ACPK commented 8 years ago

@adrianoresende I'm also hitting this issue with Rails5. Did you find a solution?

adrianoresende commented 8 years ago

@ACPK I not found solution =/ I went back to the latest version Rails4

adrianoresende commented 8 years ago

@josevalim Why you do not reopen this issue? Because Rails5

codeodor commented 8 years ago

I'm also seeing it in Rails 5, for what it's worth.

codeodor commented 8 years ago

For those having issues on Rails 5, see https://github.com/plataformatec/devise/pull/4033/files