I am using devise
(latest version - 3.2.0) with rails
(latest version - 4.0.1)
I'm doing simple authentication (without ajax or api) and getting an error for CSRF authenticity token. Check the POST request below
started POST "/users/sign_in" for 127.0.0.1 at 2013-11-08 19:48:49 +0530
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"SJnGhXXUXjncnPhCdg3muV2GYCA8CX2LVFV78pqddD4=", "user"=>
{"email"=>"[email protected]", "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" =
'[email protected]' 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)
The root url points to home#new
, which is like
class HomeController < ApplicationController
before_action :authenticate_user!
def index
end
end
Sign_in page generated html view is like:
meta tags
<meta content="authenticity_token" name="csrf-param" />
<meta content="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" name="csrf-token" />
form
<form accept-charset="UTF-8" action="/users/sign_in" class="new_user" id="new_user"
method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden
value="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" />
</div>
<div><label for="user_email">Email</label><br />
<input autofocus="autofocus" id="user_email" name="user[email]" type="email" value="" />
</div>
<div><label for="user_password">Password</label><br />
<input id="user_password" name="user[password]" type="password" /></div>
<div><input name="user[remember_me]" type="hidden" value="0" />
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1" />
<label for="user_remember_me">Remember me</label></div>
<div><input name="commit" type="submit" value="Sign in" /></div>
</form>
The authentication request even updates the last_sign_in_at
and sign_in_count
values, but when I try to access current_user
in controller it comes as nil
.
According to me it is not actually signing in user
. But then question comes "why it is updating last_sign_in_at
/sign_in_count
value in the user
table ?"
When the CSRF token is not correct, Rails will not read or do any updates to the session. It will still do any other actions the controller specifies, which explains why you see the DB update but don't end up logged in.
I notice that the authenticity_token in your log and in your page do not match. I realize this just may be because you captured a different request, but you should check that the one on the page matches the one in the log for the same request. I'm also assuming that you are using the proper tag in your view which generates a different authenticity_token each time, and are not just hard-coding the HTML input.
Do you see the same issue with forms unrelated to devise? If not, as a workaround, you can exempt your action from the CSRF check with the following code in your controller:
protect_from_forgery except: :sign_in
The odds of a CSRF attack against your sign in action seems pretty remote (<-pun) to me.
Also, if it's just with devise, then I'd suggest you file an issue with them, which you've already done.
Add this on the Application Controller (this works on Rails 5)
protect_from_forgery unless: -> { request.format.json? }
Add this to the Devise SessionController
skip_before_action :verify_authenticity_token, only: [:create]
Try it with curl
curl -X POST -v -H 'Content-Type: application/json' http://0.0.0.0:3000/users/sign_in -d '{"user" : {"email": "[email protected]", "password": "secret" }}'
There was no problem with devise gem . I removed 'rails-api' gem and my app started working.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With