Develop the right mindset for Rails security
Avoid shipping vulnerable code by learning how to prevent security issues in your Rails applications.
Get the course for $99A pull request on Rails and Devise triggered me to write this blogpost.
Password strength is more complicated than length and the enforcement of various characters, because passwords like “Admin123!” can meet certain requirements, like containing different cases, 3 digits and a special character, but can be still cracked in no time and would fall for a dictionary attack even quicker.There are plenty of resources online explaining this, so I will not repeat them.
Luckily, there is an open-source password strenght estimator that works via pattern matching and does a pretty good job at flagging easy to crack passwords: zxcvbn. There is a Ruby implementation too of the tool and that makes it easy to validate the strenght of a password.
You just need to add the gem to your app with bundle:
bundle add zxcvbn-ruby
Then you can add a validator to your user model as follows:
require 'zxcvbn'
class User < ApplicationRecord
validate :password_strength
def password_strength
if password.present?
result = Zxcvbn::Tester.new.test(password)
if result.feedback.suggestions.any?
errors.add :password, result.feedback.suggestions.join(' ' )
end
end
end
end
I suggest to additionally validate the passwords with the pwned gem, to make sure they were not in a data breach. Doing so is also pretty simple.
You need to add the gem to the Gemfile:
bundle add pwned
And you can use the custom Rails validator from the gem:
class User < ApplicationRecord
# ...
validates :password, not_pwned: true
end
By adding these two validations, you will enforce way stronger passwords then if you just require the presence of certain characters.