module Authenticatable::Models::Password

Public Instance Methods

authenticate_with_identifier(identifier, password) click to toggle source
# File lib/authenticatable/models/password.rb, line 18
def authenticate_with_identifier(identifier, password)
  if (resource = find_by_identifier(identifier))
    resource&.authenticate(password) ? resource : nil
  else
    prevent_timing_attack
  end
end
find_by_reset_password_token(token) click to toggle source
# File lib/authenticatable/models/password.rb, line 26
def find_by_reset_password_token(token)
  return nil if token.blank?

  expiration_time = Authenticatable.config.reset_password_expiration_time
  where(reset_password_token: token).where("reset_password_sent_at > ?", expiration_time.ago).first
end
flush_reset_password_token() click to toggle source

Sets the :reset_password_token attribute to a random token generated by Authenticatable::Token

# File lib/authenticatable/models/password.rb, line 45
def flush_reset_password_token
  self.reset_password_token = Authenticatable::Token.new
  self.reset_password_sent_at = Time.current
end
prevent_timing_attack() click to toggle source

Hash a random password even when a resource doesn’t exist for the given identifier. This is necessary to protect against timing/enumeration attacks - e.g. the request is faster when a resource doesn’t exist in the database if the password hashing algorithm is not called.

# File lib/authenticatable/models/password.rb, line 37
def prevent_timing_attack
  new(password: "*")
  nil
end
reset_password_token!() click to toggle source

Sets the :reset_password_token attribute to a random token generated by Authenticatable::Token and saves the record without running validations.

# File lib/authenticatable/models/password.rb, line 53
def reset_password_token!
  flush_reset_password_token
  save(validate: false)
end
update_password(secure_params) click to toggle source

Validates and sets the new password from secure_params and sets reset_password_token to nil.

# File lib/authenticatable/models/password.rb, line 60
def update_password(secure_params)
  if secure_params[:password].blank?
    errors.add(:password, :blank)
    return false
  end

  self.password = secure_params[:password]
  self.password_confirmation = secure_params[:password_confirmation]
  flush_reset_password_token if valid?
  save
end