5

Rails 7 adds `authenticate_by` method when using `has_secure_password`

 2 years ago
source link: https://blog.saeloun.com/2021/12/29/rails-7-adds-authenticate_by
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rails 7 adds `authenticate_by` method when using `has_secure_password`

Dec 29, 2021 , by Nishant Samel

2 minute read

In this exponentially growing digital world, everybody is worried about one thing.

Yes, it is SECURITY.

The need for a security is inevitable in today’s cyber ecosystem of phishing and breaches.

The fundamental mechanism used by most websites to achieve security is Authentication. In simple terms, the user/customer needs to log in using a username/email and password to access various contents of the website.

Before Rails 7:

Let’s say, we have a Customer model with the email attribute. It has a record with the email "[email protected]". We can create this customer record as follows:

Customer.create(name: "Richard Roe", email: "[email protected]", password: "password123")

Note: We are using the following code snippet to authenticate the customer. The following code returns early when a customer with a matching email is not present.

Customer.find_by(email: "[email protected]")&.authenticate("password123")

Now, the above code snippet is vulnerable to timing-based enumeration attacks, wherein an attacker can determine if a customer with the given email exists or not.

It is a common human tendency to re-use the same password across multiple websites instead of using password manager applications.

After confirming that an account exists in the database, the attacker can try a password associated with that same email address from other leaked databases over the world wide web. If an account email address is known, it allows the attacker to attempt a targeted brute force or phishing (“spear-phishing”) attack as well.

In Rails 7:

Rails 7 introduces a new class method authenticate_by.

Customer.authenticate_by(email: "[email protected]", password: "password123")

authenticate_by will cryptographically digest the given password attributes, which helps mitigate timing-based enumeration attacks. This method finds a record using the non-password attributes and then authenticates that record using the password attributes.

It returns the record, if authentication succeeds; otherwise, it returns nil.

class Customer < ActiveRecord::Base
  has_secure_password
end

Customer.create(name: "Richard Roe", email: "[email protected]", password: "password123")

Customer.authenticate_by(email: "[email protected]", password: "password123").name
# => "Richard Roe"

Customer.authenticate_by(email: "[email protected]", password: "invalid_password")
# => nil

Customer.authenticate_by(email: "[email protected]", password: "password123")
# => nil

This method raises an ArgumentError if the set of attributes doesn’t contain at least one password attribute and one non-password attribute.

Customer.authenticate_by(email: "[email protected]")
# => ArgumentError

Customer.authenticate_by(password: "password123")
# => ArgumentError

Check out the PR (including #43779, #43958, and #43997) that made this happen!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK