I need to implement password security with various flexible requirements. The requirements are essentially taken from the Sans password policy:
Strong passwords have the following characteristics:
Contain at least three of the five following character classes:
- Lower case characters
- Upper case characters
- Numbers
- Punctuation
- “Special” characters (e.g. @#$%^&*()_+|~-=`{}[]:";'<>/ etc)
- Contain at least fifteen alphanumeric characters.
There are also requirements of not allowing the users email address to appear in the password.
Ideally, I would like a gem that would handle this - it would be more widely tested and used, and we would be less likely to have bugs.
If no gem covers this, then what is the best and most-hardened method to handle these requirements? Ideally we would be able to say that we are not only safe, but safe because we have an industry standard implementation.
The gems I have found so far are:
- Devise Security Extensions, which has a very simple regex for checking that there is uppercase, lowercase, and digits
and
- Strong Password, which looks to just provide an entropy check to let the user know if their password is strong.
(We are using Rails 3.2.17 and Ruby 1.9.3, but are planning on moving to Rails 4 and Ruby 2 soon, so newer solutions are also welcome).
we've been using devise security extension for a while now. It has a lot of interesting features (e.g. password history, password expiration...).
For password complexity we wanted something that was a bit more configurable (in your example: letting customer choose how many levels of comlexity they wanted).
So we rolled out our own solution based on a score: 3 out of 5 (in you example) means that we're testing each characterisitc and give one point if it's found. If the total score is equal or greater than required score, then the password is fine.
In terms of code, our validation looks like this:
and the service that checks for the complexity looks like this:
Then it becomes very easy to add some new characteristics you want to check.
I don't think a gem is the correct thing to use here. Just use a validation:
validate :secure_password