105

I'm having a problem matching user password using devise gem in rails. User password stored on my db which is encrypted_password and i am trying to find user by password, but I don't understand how to match password from form and encrypted_password in my db.

User.find_by_email_and_password(params[:user][:email], params[:user][:password])
Sheharyar
  • 73,588
  • 21
  • 168
  • 215
poporul
  • 1,141
  • 2
  • 9
  • 10

5 Answers5

280

I think this is a better, and more elegant way of doing it:

user = User.find_by_email(params[:user][:email])
user.valid_password?(params[:user][:password])

The other method where you generate the digest from the user instance was giving me protected method errors.

Arnaud Leymet
  • 5,995
  • 4
  • 35
  • 51
joshaidan
  • 3,842
  • 1
  • 22
  • 17
34

Use Devise Methods

Devise provides you with built-in methods to verify a user's password:

user = User.find_for_authentication(email: params[:user][:email])

user.valid_password?(params[:user][:password])

For Rails 4+ with Strong Params, you can do something like this:

def login
  user = User.find_for_authentication(email: login_params[:email])

  if user.valid_password?(login_params[:password])
    user.remember_me = login_params[:remember_me]
    sign_in_and_redirect(user, event: :authentication)
  end
end

private
def login_params
  params.require(:user).permit(:email, :password, :remember_me)
end
Sheharyar
  • 73,588
  • 21
  • 168
  • 215
6

I think the better one will be this

valid_password = User.find_by_email(params[:user][:email]).valid_password?(params[:user][:password])
Uri
  • 2,306
  • 2
  • 24
  • 25
Amrit Dhungana
  • 4,371
  • 5
  • 31
  • 36
1

For 2022, devise is required to add :database_authenticatable to use valid_password? method

class User < ApplicationRecord
  devise :xxxable, :yyyable, :database_authenticatable

But, if you need only to verify the entering password just go like this

class User < ApplicationRecord
  devise :xxxable, :yyyable#, :database_authenticatable
  def valid_password?(verifying_word)
    password_digest_instance = BCrypt::Password.new(self.password_digest)
    current_password_salt = password_digest_instance.salt
    hashed_verifying_word_with_same_salt = BCrypt::Engine.hash_secret(verifying_word, current_password_salt)
    Devise.secure_compare(hashed_verifying_word_with_same_salt, self.password_digest)

Then

user = User.find_by(email: params[:user][:email])
user = nil unless user.try(:valid_password?, params[:user][:password])
Zero0Ho
  • 166
  • 1
  • 1
  • 9
0

I would suggest this.

user = User.where("email=? OR username=?", email_or_username, email_or_username).first.valid_password?(user_password)
Roshan
  • 905
  • 9
  • 21