I am using devise for authentication in a rails app. I want to add validation for some password complexity rules. It seems I don't have access to the raw password at the model level before it has been hashed. As such, I cannot validate that the raw password provided conforms to the password complexity rules that I have set. The only other way I can do this is at the controller-level. However, I'm afraid that that approach will pollute my controller. Any ideas about how I can perform the validation without having to install any other gem?
2 Answers
Here is a simple method of adding a password strength / complexity requirement at the model level.
#app/models/user.rb
validate :password_complexity
def password_complexity
if password.present?
if !password.match(/^(?=.*[a-z])(?=.*[A-Z])/)
errors.add :password, "Password complexity requirement not met"
end
end
end
Duplication: Devise custom password validation leads invalid user in console
Official docs: https://github.com/heartcombo/devise/wiki/How-To:-Set-up-simple-password-complexity-requirements

- 113
- 9

- 905
- 9
- 21
-
Hey, I tried this but ran into a small problem: `password` is actually the `encrypted_password`. Therefore, with this approach, it appears that I'd be validating the encrypted_password instead of the raw password. – monk Jul 28 '17 at 12:50
-
This is also written in the Devise page itself: https://github.com/plataformatec/devise/wiki/How-To:-Set-up-simple-password-complexity-requirements @monk - did it work for you? – dowi Dec 23 '19 at 12:46
-
how is this supposed to work if password is encrypted hash? – LE-HU Apr 04 '22 at 22:37
The best option for create complex passwords without additional gems and it also works on rails 6.0.3.2 ruby 2.7.1 https://github.com/heartcombo/devise/wiki/How-To:-Set-up-simple-password-complexity-requirements
Solution from Devise wiki (above link)
Here is a simple method of adding a password strength / complexity requirement to devise without using devise security extension (using extension is recommended.)
Example: add the following line to app/models/user.rb. Edit Regex to your liking
validate :password_complexity
def password_complexity
# Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a
return if password.blank? || password =~ /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,70}$/
errors.add :password, 'Complexity requirement not met. Length should be 8-70 characters and include: 1 uppercase, 1 lowercase, 1 digit and 1 special character'
end
Afterwards, password created by the user (or admin) must meet the regex requirements.
If the password length is checked by another method (such as config.password_length), this suits better:
def password_complexity
# Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a
return if password.blank? || password =~ /(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-])/
errors.add :password, 'Complexity requirement not met. Please use: 1 uppercase, 1 lowercase, 1 digit and 1 special character'
end

- 3,123
- 2
- 24
- 37

- 6,727
- 12
- 54
- 78