How to verify a user's password in Devise

Ruby on-RailsDevise

Ruby on-Rails Problem Overview


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])

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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.

Solution 2 - Ruby on-Rails

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

Solution 3 - Ruby on-Rails

I think the better one will be this

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

Solution 4 - Ruby on-Rails

I would suggest this.

user = User.where("email=? OR username=?", email_or_username, email_or_username).first.valid_password?(user_password)

Solution 5 - Ruby on-Rails

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])

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpoporulView Question on Stackoverflow
Solution 1 - Ruby on-RailsjoshaidanView Answer on Stackoverflow
Solution 2 - Ruby on-RailsSheharyarView Answer on Stackoverflow
Solution 3 - Ruby on-RailsAmrit DhunganaView Answer on Stackoverflow
Solution 4 - Ruby on-RailsRoshanView Answer on Stackoverflow
Solution 5 - Ruby on-RailsZero0HoView Answer on Stackoverflow