devise icon indicating copy to clipboard operation
devise copied to clipboard

Introduce config to allow for password complexity

Open kykyi opened this issue 1 year ago β€’ 60 comments

In relation to https://github.com/heartcombo/devise/issues/5591

This PR introduces application config to allow for password complexity to be granularly managed with new validation options for:

  • presence of a lower case letter
  • presence of a upper case letter
  • presence of a number
  • presence of a special character (from a list of special characters that is configurable)

These are all false by default, and configurable like:

Devise.setup do |config|
    config.password_complexity = {
      require_upper: false,    
      require_lower: false,    
      require_digit: false,   
      require_special_character: false,
      allowed_special_characters: nil
  }
end

Note

  • I haven't run any linting, I couldn't find instructions on what config was used for that πŸ˜„

kykyi avatar Nov 22 '24 03:11 kykyi

Hey @nashby if I could please request a review πŸ˜„

kykyi avatar Nov 24 '24 23:11 kykyi

Polite bump @nashby @carlosantoniodasilva πŸ˜‡

kykyi avatar Dec 03 '24 09:12 kykyi

how about modify the following configurations in the initializer file as below?

config.password_complexity = {
  upper: 1,    # At least 1 uppercase letter
  lower: 2,    # At least 2 lowercase letters
  digit: 3,    # At least 3 digits
  special: 4,  # At least 4 special characters
}

datpmt avatar Dec 09 '24 07:12 datpmt

how about modify the following configurations in the initializer file as below?

config.password_complexity = {
  upper: 1,    # At least 1 uppercase letter
  lower: 2,    # At least 2 lowercase letters
  digit: 3,    # At least 3 digits
  special: 4,  # At least 4 special characters
}

Thanks @datpmt seems like an elegant solution βœ… One issue which I could see arise however could be a clash between this and password length minimums? For ex, if you set the above, but stuck with the default 8 character minimum, you couldn't satisfy all the configured preferences. I think something like this could use your nicer syntax but also be more ergonomic with the wider validation system:

config.password_complexity = {
  upper: true,    # require upper
  lower: false,    # don't require lower
  digit: true,    # require digit
  special: true,  # require special character
  special_characters: ["!", "?", "@", "\"]
}

What do you think?

kykyi avatar Dec 09 '24 10:12 kykyi

stuck with the default 8 character minimum

config.password_complexity = {
  upper: true,       # require upper
  lower: false,      # don't require lower
  digit: true,       # require digit
  # special: true,   # redundant
  special_characters: ["!", "?", "@", "\"] # empty <=> special: false
}

@kykyi Ah I see. Cool! Let do it! :thumbsup:

datpmt avatar Dec 09 '24 11:12 datpmt

@datpmt updated to use your dict style βœ…

kykyi avatar Dec 10 '24 00:12 kykyi

Sorry for stirring the pot but I wanted to cross-post an opinion that presence of upper-cased letters, special characters and numbers has very little to do with password strength and what really contributes to the password strength is the length of the password. I'm genuinely worried that enforcing these password requirements from default will only contribute to poor user experience and potentially less secure passwords overall

More context - https://github.com/rails/rails/pull/53984#issuecomment-2551842959

Upd: I overlooked the fact that all these requirements are disabled by default which is good. So perhaps it's still useful for applications that have to comply with regulations that are out of their control. I just don't think that setting these requirements should be encouraged

nvasilevski avatar Dec 18 '24 17:12 nvasilevski

Agreed @nvasilevski I think whilst this change pushes users to increase the entropy of their passwords, setting these and forgetting could lead devs into a false sense of security βž•

kykyi avatar Dec 18 '24 22:12 kykyi

I agree with @nvasilevski - here's a specific argument against complexity requirements from the UK's National Cyber Security Centre: https://www.ncsc.gov.uk/collection/passwords/updating-your-approach#PasswordGuidance:UpdatingYourApproach-Donotusecomplexityrequirements

Recommend closure of the issue for Devise

timdiggins avatar Dec 19 '24 16:12 timdiggins

Picking up on a friendly invitation @nvasilevski given here Mates, I would like to break some glass here.

I do not believe that what you write is wrong, the contrary, I believe some very valid points have been made. I am, as probably also you, sure that we are going towards a mixture of MFA and / or passwordless login and that's overall a good thing, but the environments around us are frequently not there yet.

The problem is the world:

  • password complexity / length policies are frequenty requirements to pass audits;
  • password complexity / length should have a reference implementation to avoid errors in implementation;
  • higher complexity while not scaling as well as length is still better than nothing.

I would also mention that the Password Guidance of the NCSC that you linked is not the only opinion and as much as I love the UK, this guideline is derived from NIST. The reasoning behind it was that statistics had shown that strong requirements create weaker user generated passwords: Simply users went with "myf!stname$" instead of "some-very-s3cret-words-1n-a-$afe" as they struggled to remember too complex and to long passwords that needed to be changed frequently. Same applied to permutations "my-secretpassword$" became "my-secretpassword$$" upon frequently forced changes. Something that thanks to hashes and salts can (fortunately) not be tracked by a platform.

But all of there guidance needs to be seen in context of the remaining document that advises also:

  1. having password managers;
  2. having preferably time generated OTP tokens;
  3. being hosted on a system by somebody who understands crafting secure servers and infrastructure.

I think @kykyi made a great PR covering everything from configurability to effective resolution of the issue, maybe you could give it a look with different eyes (fearing weak integrations instead of fearing false sense of security) and we add some lines into documentation to make this a better PR covering also that the entire UTF-8 character set is only as great as the password length.

I'd really appreciate a feedback from you guys on this and I really appreciate what you are doing here, just keep in mind that stuff like NIST / NCSC guidelines are forward looking and not backward looking and need to be seen in context of the entire document. In a perfect world we would all have a password manager and OTP token for every password, but well, we all have grandmothers / fathers and parents having issues remembering 5 letters, alfanumeric or not, struggling to use a password manager. Given what devise is, it should have everything on board to make an informed decision on this topic and implement it.

fthobe avatar Jan 05 '25 16:01 fthobe

Thanks for the perspective and for weighing in @fthobe πŸ™ . I'll reopen and wait for a maintainer to merge/comment/close just so the issue can be resolved πŸ˜„

kykyi avatar Jan 05 '25 21:01 kykyi

Thanks for the perspective and for weighing in @fthobe πŸ™ . I'll reopen and wait for a maintainer to merge/comment/close just so the issue can be resolved πŸ˜„

Actually @nvasilevski did not obligate you to close it, sometimes things need some time to get traction and sometimes topics move in waves.

Be patient, open source is neither fast nor democratic πŸ˜…

fthobe avatar Jan 05 '25 21:01 fthobe

@timdiggins Hey, I would be super interested in your oppinion on my comment :)

fthobe avatar Jan 07 '25 18:01 fthobe

Ping @nvasilevski @datpmt @timdiggins

Could you retake a look at this PR and the comments made above.

fthobe avatar Jan 16 '25 08:01 fthobe

Ping @nvasilevski @datpmt @timdiggins

Could you retake a look at this PR and the comments made above.

First of all, I completely agree that the length of a password significantly impacts its strength.

In fact, many websites and company security policies require users to apply complexity rules to their passwords. This means that web applications using Devise have a valid reason to implement password complexity as a feature. Whether to enable it or not is up to the owner’s discretion.

I believe Devise should offer this option.

datpmt avatar Jan 16 '25 08:01 datpmt

I believe Devise should offer this option.

@datpmt Is this PR for you acceptable or does it need additional work?

fthobe avatar Jan 16 '25 10:01 fthobe

@fthobe Im not a maintainer/committee here so my 10c isn't worth so much πŸ˜€

A pragmatic response: My sense is that there isn't much maintainer involvement and devise is going into decline - there are CI-fix and bug fix PRs that have had no maintainer involvement so I don't think there's feature development will gain any traction.

timdiggins avatar Jan 16 '25 10:01 timdiggins

@timdiggins a lot of stuff still relies on it so we need to work with what we have.

I honestly think it's a very mature product.

Anyhow I'd really appreciate your opinion.

@carlosantoniodasilva does this PR have a shot to be integrated?

fthobe avatar Jan 16 '25 11:01 fthobe

I believe Devise should offer this option.

@datpmt Is this PR for you acceptable or does it need additional work?

I will take the time to run it locally and provide a review as soon as possible.

datpmt avatar Jan 16 '25 12:01 datpmt

@kykyi you should also put some thought in documentation.

fthobe avatar Jan 16 '25 12:01 fthobe

In fact, many websites and company security policies require users to apply complexity rules to their passwords.

Unless you meant that these applications are obligated to enforce such policy by a law that is out of their control I don't find this argument to be strong. Many applications make poor engineering and design decisions, including choosing unnecessary password/email validations. It shouldn't be a reason for libraries and frameworks to accommodate these poor choices.

Having said that,

password complexity / length policies are frequenty requirements to pass audits; password complexity / length should have a reference implementation to avoid errors in implementation;

These are strong arguments in favor of having this feature added as an optional one. There is little developers can do when it comes to complying with the law. And having a shared implementation in such cases is a huge win. I was coming from Rails perspective where the feature would become the only implementation of a "strong password" concept making it look like the only correct way to do strong passwords. Here proposal is different, it's an option that isn't enabled by default so I have nothing of a substance to say against. I just hope that applications won't reach for this feature without absolute necessity and let me use my long, secure, easy to remember and easy to type passwords.

nvasilevski avatar Jan 16 '25 14:01 nvasilevski

Hey @nvasilevski

Here Proposal is different, it's an option that isn't enabled by default so I have nothing of a substance to say against. I just hope that applications won't reach for this feature without absolute necessity and let me use my long, secure, easy to remember and easy to type passwords.

Man, to be honest, it's a mess. PCI Compliancy just to name one standard (probably the most used one) is directly asking for complexity + MFA. This practically means by law as all ecommerce companies over a certain volume need to adhere. NIST is saying the opposite.

It should be everybody's choice guided by strong conventions how to do it (which means here) and that's why I am pushing for it.

Also I believe it's not good to run for anything to a separate gem, this is really low hanging fruit and could be done with relatively little effort here and thanks to @kykyi we are half the way there :)

fthobe avatar Jan 16 '25 14:01 fthobe

@datpmt i have some time on Wednesday to test this with spree and solidus. Is there anything I should be particularly attentive off?

fthobe avatar Jan 20 '25 09:01 fthobe

@datpmt i have some time on Wednesday to test this with spree and solidus. Is there anything I should be particularly attentive off?

@fthobe You need to pay attention to the require_special and special_characters params. I think require_special is somewhat redundant. If I do it, I will only use special_characters. If it's empty, then no special character is required, and vice versa.

datpmt avatar Jan 20 '25 15:01 datpmt

@kykyi can you implement a change? @datpmt argument of uniting special and special_characters is very valid to keep everything streamlined. I can test it out on Wednesday with some gems that use devise.

fthobe avatar Jan 20 '25 15:01 fthobe

@kykyi thanks!

@datpmt this should be as you wanted it.

fthobe avatar Jan 21 '25 08:01 fthobe

@kykyi also given the small amount of files involved you could consider to squash the commits as "merge..." is not a great commit Name for clarity.

fthobe avatar Jan 21 '25 08:01 fthobe

@datpmt worked for me, did you encounter any issues?

fthobe avatar Jan 29 '25 16:01 fthobe

@datpmt Baden (@kykyi ) was kind enough to make the changes. Could we carry this over the finish line?

fthobe avatar Mar 06 '25 18:03 fthobe

@fthobe for sure, thanks @datpmt, we need a maintainer to approve though?

kykyi avatar Mar 06 '25 20:03 kykyi