Devise ERROR: Auth token has already been taken - ruby-on-rails

Trying to signup in my RoR webapp give me the Devise Message "Auth token has already been taken"
Also, the webapp have an API and works fine, doesn't give any message, this only happen when I'm trying to use the HTML view.
user_controller.rb
before_action :set_user, only: [:show, :edit, :update, :destroy]
# DELETE /users/:id.:format
def destroy
# authorize! :delete, #user
#user.destroy
respond_to do |format|
format.html { redirect_to root_url }
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
accessible = [ :name, :email ]
accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
params.require(:user).permit(accessible)
end
User.rb
validates :auth_token, uniqueness: true
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_create :generate_authentication_token!
def generate_authentication_token!
begin
self.auth_token = Devise.friendly_token
end while self.class.exists?(auth_token: auth_token)
end
logs
Started GET "/users/sign_up" for 127.0.0.1 at 2015-06-30 09:31:46 -0500
Processing by Devise::RegistrationsController#new as HTML
Rendered devise/registrations/new.html.haml within layouts/application (12.9ms)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."auth_token" IS NULL LIMIT 1
Rendered layouts/_navigation_links.html.haml (2.1ms)
Rendered layouts/_navigation.html.haml (3.4ms)
Rendered layouts/_messages.html.haml (0.2ms)
Completed 200 OK in 132ms (Views: 117.0ms | ActiveRecord: 1.5ms)
Started POST "/users" for 127.0.0.1 at 2015-06-30 09:32:00 -0500
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"20w9AXmACwggvPocKfLBdrxQRasT5OiaC7niuzooBBm3BAp8xkN6VLWyxZLRoLIpFPEIIdkxZRd9CCwsJxkeUA==", "user"=>{"email"=>"hola#x.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
(0.1ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."auth_token" = '' LIMIT 1
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'hola#x.com' LIMIT 1
(0.1ms) ROLLBACK
Rendered devise/registrations/new.html.haml within layouts/application (3.2ms)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."auth_token" IS NULL LIMIT 1
Rendered layouts/_navigation_links.html.haml (1.5ms)
Rendered layouts/_navigation.html.haml (2.1ms)
Rendered layouts/_messages.html.haml (0.2ms)
Completed 200 OK in 232ms (Views: 134.4ms | ActiveRecord: 1.2ms)
Started GET "/assets/jquery/jquery-bb5529929fa5581a780a38ecb7470f2c.js?body=1" for 127.0.0.1 at 2015-06-30 09:32:00 -0500

Follow the following
1) Open Rails console
rails console
2) Get the total count of users
user = User.all
user.count
this should be 1
3) Get the user and check the auth token
user = User.last
user.auth_token
auth token would be an empty string which is the reason your command is failing as the user doesn't have valid auth token
4) Create a valid auth token for the user
user.auth_token = Devise.friendly_token
user.save
It would create a valid auth token for the user and save it
5) Now you can run your commands and it would work perfectly
Cheers! :)

It's probably because you already have users in your db without auth_token,
use Devise.friendly_token to update those users with a token

Related

devise rails application redirecting to users/sign_in

all -
New to rails and web development. I started a new rails application and am using Devise. Whenever I hit Log In on the users/sign_in page, the page just refreshes.
Here is my terminal log after clicking Log In. It's showing the POST, I'm not sure why it's ultimately rendering devise/sessions/new.html....:
Started POST "/users/sign_in" for ::1 at 2017-10-02 09:19:20 -0400
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ot4EJmxLvXrPpa6WYyqCXHxAUT3DcHimrIfw8HGyu5j7yuXvWArEkWzx59Dj3GZrlVDpgS/xSgXFSIt+mQqQnw==", "user"=>{"email"=>"bob#good.company", "password"=>"[FILTERED]"}, "commit"=>"Log in!"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "bob#good.company"], ["LIMIT", 1]]
(0.1ms) begin transaction
(0.1ms) commit transaction
Completed 401 Unauthorized in 162ms (ActiveRecord: 0.3ms)
Started GET "/users/sign_in" for ::1 at 2017-10-02 09:19:21 -0400
Processing by Devise::SessionsController#new as HTML
Rendering devise/sessions/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (1.2ms)
Rendered devise/sessions/new.html.erb within layouts/application (4.6ms)
Completed 200 OK in 45ms (Views: 43.5ms | ActiveRecord: 0.0ms)
My routes.rb
Rails.application.routes.draw do
get 'charges/create'
devise_for :users
get 'welcome/index'
get 'welcome/about'
resources :wikis
resources :charges, only: [:new, :create]
end
and my User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :wikis
before_save { self.email = email.downcase }
enum role: [:standard, :admin, :premium]
after_initialize { self.role ||= :standard }
end
Thank you for any direction and please let me know if I can provide any more details / code samples etc.
please update this user password from console
this happened because of you only provided only password attribute, you skipped password_confirmation attribute
eg User.where(email: "Youremail#email.com").update(password: "password", password_confirmation: "password")

Devise Admin Edit User failing for password "can't be blank". What are the possible levels of code down to DB that can block this?

I've got Devise and omniauth gems. I more or less followed railscasts for multiple authentications so have Users and Authentications models.
I've managed to have a user update their own profile without a password when they have authentications.
class RegistrationsController < Devise::RegistrationsController
def update_resource(resource, params)
if current_user.authentications.empty?
resource.update_with_password(account_update_params)
else
params.except("current_password")
resource.update_without_password(account_update_params)
end
end
end
routes.rb:
devise_for :users, :controllers => {registrations: 'registrations'}, path_prefix: 'my'
resources :users
users/edit.html.haml
<%= bootstrap_form_for #user, html: {multipart: true} do |f| %>
...
<%= f.submit "Update" %>
users_controller.rb
def update
#user = User.find(params[:id])
Rails.logger.info(params.inspect)
if #user.update_without_password(account_update_params)
flash[:success] = "User updated by admin."
redirect_to #user
else
Rails.logger.info(#user.errors.inspect)
flash[:alert] = "User update by admin failed to save"
render 'edit'
end
private
def account_update_params
params.require(:user).permit(:email, :first_name, :last_name, :username, :dob,:city, :state, :zip, :password, :password_confirmation, :current_password)
end
end
user.rb
def update_without_password(params, *options)
params.delete(:password)
params.delete(:password_confirmation)
result = update_attributes(params, *options)
clean_up_passwords
result
end
Log file:
Started GET "/users/2/edit" for 127.0.0.1 at 2017-06-18 19:45:01 -0400
Processing by UsersController#edit as HTML
Parameters: {"id"=>"2"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Rendering users/edit.html.erb within layouts/application
Rendered users/edit.html.erb within layouts/application (12.6ms)
Rendered layouts/_shim.html.erb (0.3ms)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendered layouts/_sidenav.html.erb (1.0ms)
Rendered layouts/_nav_top.html.erb (0.4ms)
Rendered layouts/_notice.html.erb (0.3ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 193ms (Views: 190.3ms | ActiveRecord: 0.3ms)
Started PATCH "/users/2" for 127.0.0.1 at 2017-06-18 19:45:04 -0400
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SwkF8C+P6iExhc1ju91C9xFgaR5GSKwy8KFJUaBtHCTKzEXmPIKhaAFHlfMO+6u4/UOM0y2IAAIkpfTsuBOX6g==", "user"=>{"first_name"=>"Bobby", "last_name"=>"", "username"=>"", "dob"=>"", "gender"=>"", "address1"=>"", "address2"=>"", "state"=>"", "zip"=>"", "email"=>"test#test.com"}, "commit"=>"Update", "id"=>"2"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
<ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"SwkF8C+P6iExhc1ju91C9xFgaR5GSKwy8KFJUaBtHCTKzEXmPIKhaAFHlfMO+6u4/UOM0y2IAAIkpfTsuBOX6g==", "user"=>{"first_name"=>"Bobby", "last_name"=>"", "username"=>"", "dob"=>"", "gender"=>"", "address1"=>"", "address2"=>"", "state"=>"", "zip"=>"", "email"=>"test#test.com"}, "commit"=>"Update", "controller"=>"users", "action"=>"update", "id"=>"2"} permitted: false>
(0.1ms) begin transaction
Authentication Exists (0.1ms) SELECT 1 AS one FROM "authentications" WHERE "authentications"."user_id" = ? LIMIT ? [["user_id", 2], ["LIMIT", 1]]
Authentication Exists (0.0ms) SELECT 1 AS one FROM "authentications" WHERE "authentications"."user_id" = ? LIMIT ? [["user_id", 2], ["LIMIT", 1]]
(0.0ms) rollback transaction
#<ActiveModel::Errors:0x007f9cf49d1758 #base=#<User id: 2, email: "test#test.com", created_at: "2017-06-18 16:05:51", updated_at: "2017-06-18 16:05:51", username: "", first_name: "Bobby", last_name: "", dob: nil, gender: "", address1: "", address2: "", city: nil, state: "", zip: "", admin: false, phone: nil>, #messages={:password=>["can't be blank"]}, #details={:password=>[{:error=>:blank}]}>
Rendering users/edit.html.erb within layouts/application
Rendered users/edit.html.erb within layouts/application (5.1ms)
Rendered layouts/_shim.html.erb (0.3ms)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendered layouts/_sidenav.html.erb (0.9ms)
Rendered layouts/_nav_top.html.erb (0.5ms)
Rendered layouts/_notice.html.erb (0.3ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 199ms (Views: 188.4ms | ActiveRecord: 0.7ms)
The message #messages={:password=>["can't be blank"] is pointing to the answer, but everything I've tried isn't removing this requirement. I thought that Devise's update_without_password method would work out of the box.
I've even tried this at the top in user.rb.
validates :password, presence: true, length: {minimum: 5, maximum: 120}, on: :create
validates :password, length: {minimum: 5, maximum: 120}, on: :update, allow_blank: true
Thanks for the help SO!
Check out your UsersController. You are using except on your paramsand then using account_update_params in the conditional. except doesn't exactly delete the key and value from the Hash.
This is a helpful SO answer that should fix your situation here .
If that doesn't help I would follow Devise's existing guide on how to achieve this:
Make sure you follow the Devise guide for allowing users to edit their account without providing a password. I'm not sure what you are trying to do in your User model, are you trying to overwrite the Devise method?
If you are trying to overwrite the Devise method you should look at the method itself:
def update_without_password(params, *options)
params.delete(:email)
super(params)
end
If you are using this method, you should probably override this method to protect other attributes you would not like to be updated without a password.
Change your RegistrationsController to the match the docs:
def update_resource(resource, params)
resource.update_without_password(params)
end
Then follow the remaining two steps and confirm your edited your view and routes.
If you need to make any changes authentication wise be sure to change the update_resource method.

Rails + Devise: if user_signed_in? not working

I first discovered an issue where it didn't appear as if the user is getting logged in with this logic:
_header.html.erb:
<% if user_signed_in? %>
<li><%= link_to "Log out", destroy_user_session_path, method: :delete %></li>
<% else %>
<li><%= link_to "Sign in", new_user_session_path %></li>
<% end %>
Then I tried adding this to application_controller.rb:
before_filter :authenticate_user!
And I kept getting looped back to the login page (even with valid credentials).
It appears as if my user sessions aren't working — although I can see on my RailsAdmin console that the sign in count and last sign in date are showing as if they are logging in.
Here's my user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :omniauthable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
belongs_to :company
has_and_belongs_to_many :productlines
end
And my routes.rb:
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks" }
root 'productlines#index'
end
And omniauth_callbacks_controller.rb:
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
flash.notice = "Signed in through Google"
sign_in_and_redirect #user
return
else
session["devise.user_attributes"] = #user.attributes
flash.notice = "You are almost Done! Please provide a password to finish setting up your account"
redirect_to new_user_registration_path
end
end
end
Update: Here is my application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }
before_filter :productline
def productline
#productlines = Productline.all
end
end
Every time I sign in, I'm rerouted back to the root_path and the "Sign In" link still appears.
Edit: Here is the log output when I click Sign In:
Started POST "/users/sign_in" for ::1 at 2015-07-06 23:20:15 -0400
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"6Eh4Qw3qErGmsppatErFZYhTOZHs8DhCOMXqGAMrBzRdTd72L5rIGAChLDvnI/GzOv1kQsyL43o/B6AQQtnk4Q==", "user"=>{"email"=>"broy#bullhorn.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT 1 [["email", "b#gmail.com"]]
(0.1ms) begin transaction
SQL (0.3ms) UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = ? [["last_sign_in_at", "2015-07-07 03:17:08.826634"], ["current_sign_in_at", "2015-07-07 03:20:15.963289"], ["sign_in_count", 93], ["updated_at", "2015-07-07 03:20:15.964239"], ["id", 4]]
(1.5ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 73ms (ActiveRecord: 2.1ms)
Started GET "/" for ::1 at 2015-07-06 23:20:15 -0400
Processing by ProductlinesController#index as HTML
Productline Load (0.1ms) SELECT "productlines".* FROM "productlines"
Rendered productlines/index.html.erb within layouts/application (2.1ms)
Rendered layouts/_header.html.erb (1.7ms)
Completed 200 OK in 48ms (Views: 47.3ms | ActiveRecord: 0.1ms)
Started GET "/" for ::1 at 2015-07-06 23:20:16 -0400
Processing by ProductlinesController#index as HTML
Productline Load (0.2ms) SELECT "productlines".* FROM "productlines"
Rendered productlines/index.html.erb within layouts/application (104.8ms)
Rendered layouts/_header.html.erb (1.1ms)
Completed 200 OK in 155ms (Views: 154.1ms | ActiveRecord: 0.2ms)
Do you want to put an exception in first on your authenticate user? That way it is not trying to run an authentication before current_user/#user/etc has even been set. For example if your root is index:
before_action :authenticate_user!, :except => [:index]
Then - be sure to have the better_errors gem and throw in some nonsense jibberish in your if user_signed_in? statement, refresh the page to trigger the console in the browser. See if #user or current_user or what you are using got set at all in the first place. I would then debug backwards from there.
https://github.com/charliesome/better_errors
Finally here is a stackoverflow link I came upon with a similar issue and a few answers below:
Rails devise: user_signed_in? not working

Rails 4 devise_invitable invitation token invalid

I have been following Ryan Boland's excellent Rails multitenancy tutorial, but have run into a snag with devise_invitable. I am using...
Rails 4.1.5
devise 3.3.0
devise_invitable 1.3.6
Postgresql
I create a new account and user/account owner on a chosen subdomain (mysubdomain.lvh.me:3000), from which I can send a user invitation just fine. I open the invitation link in an incognito Chrome session to ensure I am not logged in or have any current session. Upon clicking on the invitation link, I am redirected to the sign in page (mysubdomain.lvh.me:3000/users/sign_in) and see a flash notice: "The invitation token provided is not valid!"
I am using a very simple mailer view (app/views/devise/mailer/invitation_instructions.html.erb)...
<%= link_to 'Accept invitation', accept_invitation_url(#resource, :invitation_token => #token) %>
As you can see, I ensured the use of #token, as described here.
Upon creating the invitation, I have confirmed the invitation token is saved to the database (in this case for hey#test.com - d1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9). I have confirmed this matches the token on invitation lookup upon acceptance request (see below traces). Still, it redirects to user sign in page rather than completing sign up, and also displays in the trace log "Filter chain halted as :resource_from_invitation_token rendered or redirected". The user remains uncomfirmed in the end after this transaction.
Any ideas on what might be going wrong for me here? I am including logs, my application controller, and my devise config below...
Here is the trace log for the invitation creation:
Started POST "/users/invitation" for 127.0.0.1 at 2014-09-07 01:28:33 +0800
Processing by Devise::InvitationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"BiIQ95wwdQz3CJ0+OoLOE9xHHvxhloHsRHrxsqf1D2Q=", "user"=>{"email"=>"hey#test.com"}, "commit"=>"Invite User"}
User Load (4.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Account Load (0.4ms) SELECT "public"."accounts".* FROM "public"."accounts" WHERE "public"."accounts"."subdomain" = 'mysubdomain' LIMIT 1
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'hey#test.com' ORDER BY "users"."id" ASC LIMIT 1
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = 'd1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9' ORDER BY "users"."id" ASC LIMIT 1
(0.1ms) BEGIN
SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "invitation_created_at", "invitation_sent_at", "invitation_token", "invited_by_id", "invited_by_type", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["created_at", "2014-09-06 17:28:34.296123"], ["email", "hey#test.com"], ["invitation_created_at", "2014-09-06 17:28:34.294987"], ["invitation_sent_at", "2014-09-06 17:28:34.294987"], ["invitation_token", "d1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9"], ["invited_by_id", 1], ["invited_by_type", "User"], ["updated_at", "2014-09-06 17:28:34.296123"]]
(2.2ms) COMMIT
Rendered devise/mailer/invitation_instructions.html.erb (1.3ms)
Devise::Mailer#invitation_instructions: processed outbound mail in 23.5ms
Sent mail to hey#test.com (26.0ms)
Date: Sun, 07 Sep 2014 01:28:34 +0800
From: please-change-me-at-config-initializers-devise#example.com
Reply-To: please-change-me-at-config-initializers-devise#example.com
To: hey#test.com
Message-ID: <...>
Subject: Invitation instructions
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Accept invitation
Redirected to http://mysubdomain.lvh.me:3000/users
Completed 302 Found in 888ms (ActiveRecord: 10.0ms)
Here is the trace upon following the invitation link...
Started GET "/users/invitation/accept?invitation_token=3GXDmi7NntDRdhvo57q5" for 127.0.0.1 at 2014-09-07 01:28:38 +0800
Processing by Devise::InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"3GXDmi7NntDRdhvo57q5"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = 'd1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9' ORDER BY "users"."id" ASC LIMIT 1
Redirected to http://mysubdomain.lvh.me:3000/users/sign_in
Filter chain halted as :resource_from_invitation_token rendered or redirected
Completed 302 Found in 5ms (ActiveRecord: 0.6ms)
Started GET "/users/sign_in" for 127.0.0.1 at 2014-09-07 01:28:38 +0800
Processing by Devise::SessionsController#new as HTML
Account Load (0.4ms) SELECT "public"."accounts".* FROM "public"."accounts" WHERE "public"."accounts"."subdomain" = 'mysubdomain' LIMIT 1
Rendered devise/shared/_links.erb (0.7ms)
Rendered devise/sessions/new.html.erb within layouts/application (4.4ms)
Completed 200 OK in 21ms (Views: 16.6ms | ActiveRecord: 1.3ms)
Here is my application_controller for good measure...
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :load_schema, :authenticate_user!, :set_mailer_host
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :company, :email, :password, :password_confirmation, :remember_me, :image, :image_cache)}
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:first_name, :last_name, :company, :email, :password_confirmation, :current_password, :image, :image_cache)}
end
private
def load_schema
Apartment::Database.switch('public')
return unless request.subdomain.present?
if current_account
Apartment::Database.switch(current_account.subdomain)
else
redirect_to root_url(subdomain: false)
end
end
def current_account
#current_account ||= Account.find_by(subdomain: request.subdomain)
end
helper_method :current_account
def set_mailer_host
subdomain = current_account ? "#{current_account.subdomain}." : ""
ActionMailer::Base.default_url_options[:host] = "#{subdomain}lvh.me:3000"
end
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
end
def after_invite_path_for(resource)
users_path
end
end
Here is my Devise initializer (config/initializers/devise.rb), I have added the line "config.allow_insecure_token_lookup = true" to see if this helps, but to no avail...
Devise.setup do |config|
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
require 'devise/orm/active_record'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.password_length = 8..128
config.sign_out_via = :delete
config.allow_insecure_token_lookup = true
end
I'd prefer to comment but I have only 36 points and am not allowed so here's an incomplete answer:
this is the code from devise_invitable InvitationsController which is redirecting your request
def resource_from_invitation_token
unless params[:invitation_token] && self.resource = resource_class.find_by_invitation_token(params[:invitation_token], true)
set_flash_message(:alert, :invitation_token_invalid)
redirect_to after_sign_out_path_for(resource_name)
end
end
in your rails console try running:
token = '3GXDmi7NntDRdhvo57q5' #the token sent in the invitation email
User.find_by_invitation_token(token, true)
and see if that returns your User. It probably won't but maybe this will bring you closer to an answer. I hope so.

Can't authenticate on Rails with BCrypt - password hashes are different

I am trying to create a simple authentication system but I seem to have a problem.
The signup process works fine, but when I try to login with the exact same information, I can't (I get "Invalid email or password"). As I saw, the hash comparison returns false. Here is my code:
#sessions_controller.rb
def create
user = User.authenticate(params[:email], params[:password])
if user
session[:user_id] = user.id
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
and
class User < ActiveRecord::Base
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :name
validates_presence_of :email
validates_uniqueness_of :email
def self.authenticate(email, password)
user = User.where(email: email).first
# throw Exception.new(user.password_hash) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.hlKKv4ajX/dX9D/xNGmZoajJTdGG4N.>
# throw Exception.new(user.password_salt) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.>
# throw Exception.new(BCrypt::Engine.hash_secret(password, user.password_salt)) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.O62xalJit020Jb0g5XDdB5V8dGMslQS>
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
So, as you can see in the commented lines in user.rb, the password hash that I get when trying to log in is not the same with the original one. Obviously, the password I enter is the correct one.
user.password_hash = $2a$10$9FHhPyb7BW01ktwTTgZHX.hlKKv4ajX/dX9D/xNGmZoajJTdGG4N.
user.password_salt = $2a$10$9FHhPyb7BW01ktwTTgZHX.
BCrypt::Engine.hash_secret(password, user.password_salt) = $2a$10$9FHhPyb7BW01ktwTTgZHX.O62xalJit020Jb0g5XDdB5V8dGMslQS
Can you please give me a hint here? What is that I do wrong?
Thanks a lot!
//later edit: also adding the users controller, perhaps this can help.
class UsersController < ApplicationController
def new
#user = User.new(user_params)
end
def create
#user = User.new(user_params)
if #user.save
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
end
private
def user_params
params.fetch(:user).permit(:name, :email, :password, :password_confirmation) if params[:user]
end
end
Edit: posting the logs for signing up/logging in
Started GET "/sign_up" for 127.0.0.1 at 2013-10-11 11:23:13 +0300
Processing by UsersController#new as HTML
Rendered users/new.html.erb within layouts/application (31.8ms)
Completed 200 OK in 48ms (Views: 41.8ms | ActiveRecord: 1.2ms)
Started POST "/users" for 127.0.0.1 at 2013-10-11 11:24:30 +0300
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LPLEs9at6BLGgjikYynnEzA/JAMMVl9IYGId1zEyNEg=", "user"=>{"name"=>"johntest", "email"=>"johntest#johntest.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Create User"}
(0.1ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'johntest#johntest.com' LIMIT 1
SQL (0.3ms) INSERT INTO `users` (`created_at`, `email`, `name`, `password_hash`, `password_salt`, `updated_at`) VALUES ('2013-10-11 08:24:30', 'johntest#johntest.com', 'johntest', '$2a$10$tpDFvkFUC.OPckDm6xacU.xkjFmECg2CDpsi3cjTJNX6K58ujHOn6', '$2a$10$tpDFvkFUC.OPckDm6xacU.', '2013-10-11 08:24:30')
(39.2ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 141ms (ActiveRecord: 40.0ms)
Started GET "/" for 127.0.0.1 at 2013-10-11 11:24:30 +0300
Processing by TroublesController#frontpage as HTML
Trouble Load (0.2ms) SELECT `troubles`.* FROM `troubles`
CACHE (0.0ms) SELECT `troubles`.* FROM `troubles`
Rendered troubles/_marker_infowindow.html.erb (0.8ms)
Rendered troubles/_marker_infowindow.html.erb (0.1ms)
Rendered /home/alex/.rvm/gems/ruby-2.0.0-p247/gems/gmaps4rails-1.5.6/app/views/gmaps4rails/_gmaps4rails.html.erb (1.9ms)
Rendered troubles/frontpage.html.erb within layouts/application (3.9ms)
Completed 200 OK in 21ms (Views: 13.5ms | ActiveRecord: 0.2ms)
[...](loading assets)
Started GET "/log_in" for 127.0.0.1 at 2013-10-11 11:24:52 +0300
Processing by SessionsController#new as HTML
Rendered sessions/new.html.erb within layouts/application (1.1ms)
Completed 200 OK in 14ms (Views: 12.8ms | ActiveRecord: 0.0ms)
Started POST "/sessions" for 127.0.0.1 at 2013-10-11 11:25:05 +0300
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LPLEs9at6BLGgjikYynnEzA/JAMMVl9IYGId1zEyNEg=", "name"=>"johntest", "email"=>"johntest#johntest.com", "password"=>"[FILTERED]", "commit"=>"Log in"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'johntest#johntest.com' ORDER BY `users`.`id` ASC LIMIT 1
Rendered sessions/new.html.erb within layouts/application (1.7ms)
Completed 200 OK in 99ms (Views: 10.9ms | ActiveRecord: 0.4ms)
[...](loading assets)
So I went to the sign up page, filled in the details, I was forwarded to the homepage and it said "Signed up!". I clicked login, entered the details and it says "Invalid email or password".
Bcrypt is decrypting the right way but the culprit in your code is the before_save :encrypt_password just change the before save event as before_create event. with before_save , Every time you update the user record encrypt_password is called and it is encrypting the password field that way you are losing the first encrypted password which never matches though you give the correct password. I got stuck up with the same issue, after a deep analysis I got to know the fix.

Resources