Rails 7 adds `authenticate_by` method when using `has_secure_password`
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.
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!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK