New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #16860 -- Added password validation to django.contrib.auth #4276

Closed
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
@mxsasha
Member

mxsasha commented Mar 8, 2015

  • Aggregate all validation errors.
  • Aggregate all requirements with HTML lists.
  • Call a method on each validator after a successful change.
  • Validator for most common passwords.
  • See whether similarity errors can be made more specific.
  • Look into performance impact of current similarity validator.
  • Tests
  • Docs
  • Look into alternative way for validators to return their failures per Aymeric's suggestion.
  • Look into alternative design which does not require a global setting.
  • Ensure the common password list is cached.
  • Add validator to check for fully numerical passwords.
  • Release notes

https://code.djangoproject.com/ticket/16860
Mailing list discussion on: https://groups.google.com/forum/#!topic/django-developers/9GBhgGXmEKs

@mxsasha mxsasha assigned kmtracey and unassigned kmtracey Mar 14, 2015

@mxsasha

This comment has been minimized.

Show comment
Hide comment
@mxsasha

mxsasha Mar 14, 2015

Member

Didn't actually mean to assign this to Karen, must have misclicked somewhere :)

Member

mxsasha commented Mar 14, 2015

Didn't actually mean to assign this to Karen, must have misclicked somewhere :)

@mxsasha

This comment has been minimized.

Show comment
Hide comment
@mxsasha

mxsasha Apr 11, 2015

Member

I don't know entirely what's going on, but those build failures do not appear to be related to the patch:

 > git checkout -f fe70cd410fbc419a4881099ab3034d0f72d629ed
FATAL: Could not checkout null with start point fe70cd410fbc419a4881099ab3034d0f72d629ed
hudson.plugins.git.GitException: Could not checkout null with start point fe70cd410fbc419a4881099ab3034d0f72d629ed

Most platforms do seem to succeed.

Member

mxsasha commented Apr 11, 2015

I don't know entirely what's going on, but those build failures do not appear to be related to the patch:

 > git checkout -f fe70cd410fbc419a4881099ab3034d0f72d629ed
FATAL: Could not checkout null with start point fe70cd410fbc419a4881099ab3034d0f72d629ed
hudson.plugins.git.GitException: Could not checkout null with start point fe70cd410fbc419a4881099ab3034d0f72d629ed

Most platforms do seem to succeed.

@MarkusH

This comment has been minimized.

Show comment
Hide comment
@MarkusH

MarkusH Apr 11, 2015

Member

That's one of Jenkins occasional hiccups. No need to worry.

Member

MarkusH commented Apr 11, 2015

That's one of Jenkins occasional hiccups. No need to worry.

@@ -236,3 +236,173 @@ from the ``User`` model.
Checks if the given string is a hashed password that has a chance
of being verified against :func:`check_password`.

This comment has been minimized.

@aaugustin

aaugustin Apr 11, 2015

Member

Extra blank line :-)

@aaugustin

aaugustin Apr 11, 2015

Member

Extra blank line :-)

This comment has been minimized.

@aaugustin

aaugustin Apr 11, 2015

Member

There are a few other double line breaks below.

@aaugustin

aaugustin Apr 11, 2015

Member

There are a few other double line breaks below.

This comment has been minimized.

@mxsasha

mxsasha May 16, 2015

Member

Fixed.

@mxsasha

mxsasha May 16, 2015

Member

Fixed.

AUTH_PASSWORD_VALIDATORS
------------------------

This comment has been minimized.

@timgraham

timgraham Apr 11, 2015

Member

Add "Default: ..." like other settings. Also ".. versionadded:: 1.9"

@timgraham

timgraham Apr 11, 2015

Member

Add "Default: ..." like other settings. Also ".. versionadded:: 1.9"

This comment has been minimized.

@mxsasha

mxsasha May 16, 2015

Member

Fixed.

@mxsasha

mxsasha May 16, 2015

Member

Fixed.

@MarkusH

This comment has been minimized.

Show comment
Hide comment
@MarkusH

MarkusH Apr 11, 2015

Member

As @aaugustin mentioned elsewhere, compression the common passwords list sounds like a good idea in combination with customizing its location.

How hard would it be to add some autodetection if the file needs to be unzipped or is already a plain-text file? Plain text files are easier to maintain for project specific lists, I think.

Member

MarkusH commented Apr 11, 2015

As @aaugustin mentioned elsewhere, compression the common passwords list sounds like a good idea in combination with customizing its location.

How hard would it be to add some autodetection if the file needs to be unzipped or is already a plain-text file? Plain text files are easier to maintain for project specific lists, I think.

'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',

This comment has been minimized.

@wimfeijen

wimfeijen Apr 12, 2015

Contributor

Why is NAME in capitals?

For comparison, DATABASES and CACHES use lower-case 'default' and then capitals, LOGGING uses lower-case only.

@wimfeijen

wimfeijen Apr 12, 2015

Contributor

Why is NAME in capitals?

For comparison, DATABASES and CACHES use lower-case 'default' and then capitals, LOGGING uses lower-case only.

This comment has been minimized.

@MarkusH

MarkusH Apr 12, 2015

Member

Because it's a predefined identifier, similar to ENGINE and NAME in the DATABASES setting and BACKEND and DIRS in TEMPLATES.

@MarkusH

MarkusH Apr 12, 2015

Member

Because it's a predefined identifier, similar to ENGINE and NAME in the DATABASES setting and BACKEND and DIRS in TEMPLATES.

@jezdez

This comment has been minimized.

Show comment
Hide comment
@jezdez

jezdez Apr 12, 2015

Contributor

Ough, is a new setting really required for this?

Contributor

jezdez commented Apr 12, 2015

Ough, is a new setting really required for this?

@timgraham timgraham changed the title from WIP - Added password validation to django.contrib.auth to [WIP] Fixed #16860 -- Added password validation to django.contrib.auth Apr 16, 2015

@mxsasha

This comment has been minimized.

Show comment
Hide comment
@mxsasha

mxsasha Apr 26, 2015

Member

@jezdez, @aaugustin: as both of you have proposed to tie this to the User model, could you write up a short example? I may have some concerns about that design, but I'd rather form an opinion on an example rather than my imagination of what I think your idea might be. Perhaps I'm entirely mistaken.

As this is a more fundamental design discussion, perhaps this would fit best on the django-developers list rather than this PR.

Member

mxsasha commented Apr 26, 2015

@jezdez, @aaugustin: as both of you have proposed to tie this to the User model, could you write up a short example? I may have some concerns about that design, but I'd rather form an opinion on an example rather than my imagination of what I think your idea might be. Perhaps I'm entirely mistaken.

As this is a more fundamental design discussion, perhaps this would fit best on the django-developers list rather than this PR.

@mxsasha mxsasha changed the title from [WIP] Fixed #16860 -- Added password validation to django.contrib.auth to Fixed #16860 -- Added password validation to django.contrib.auth Jun 5, 2015

return validators
def validate_password(password, user=None, password_validators=None):

This comment has been minimized.

@carljm

carljm Jun 5, 2015

Member

If I were writing this from scratch, I'd consider "a bunch of functions that all take an optional password_validators arg and call get_default_password_validators() if it's not given" to be an indication that perhaps a higher-level class is in order that you can instantiate with a set of password validators and then call methods on (and a default instance of that class based on settings could be provided at module level).

But I don't feel strongly enough about this to suggest actually rewriting it on that model.

@carljm

carljm Jun 5, 2015

Member

If I were writing this from scratch, I'd consider "a bunch of functions that all take an optional password_validators arg and call get_default_password_validators() if it's not given" to be an indication that perhaps a higher-level class is in order that you can instantiate with a set of password validators and then call methods on (and a default instance of that class based on settings could be provided at module level).

But I don't feel strongly enough about this to suggest actually rewriting it on that model.

This comment has been minimized.

@mxsasha

mxsasha Jun 6, 2015

Member

That's a sensible design. However, the custom validator setup is expected to be quite uncommon: you only need this if you have multiple different sets of validators within the same Django project. So for most people, it's now as simple as calling validate_password() - which would get slightly more complicated in your proposed design. I also don't feel strongly, so I'll leave it as is.

@mxsasha

mxsasha Jun 6, 2015

Member

That's a sensible design. However, the custom validator setup is expected to be quite uncommon: you only need this if you have multiple different sets of validators within the same Django project. So for most people, it's now as simple as calling validate_password() - which would get slightly more complicated in your proposed design. I also don't feel strongly, so I'll leave it as is.

return _("Your password must contain at least %(min_length)d characters.") % {'min_length': self.min_length}
class UserAttributeSimilarityValidator(object):

This comment has been minimized.

@carljm

carljm Jun 5, 2015

Member

I suppose there's no reasonable way around the fact that this provides no protection if the attributes are later changed after the password is chosen. Unless validators gained an optional method where they could be notified of any change to the user model (optionally; this would have to be an API called explicitly by the user since Django doesn't provide an edit-user form).

@carljm

carljm Jun 5, 2015

Member

I suppose there's no reasonable way around the fact that this provides no protection if the attributes are later changed after the password is chosen. Unless validators gained an optional method where they could be notified of any change to the user model (optionally; this would have to be an API called explicitly by the user since Django doesn't provide an edit-user form).

This comment has been minimized.

@carljm

carljm Jun 5, 2015

Member

Never mind, even such an API would be useless since the raw password is no longer available after its initially set. So there really is no way around that limitation of this validator.

@carljm

carljm Jun 5, 2015

Member

Never mind, even such an API would be useless since the raw password is no longer available after its initially set. So there really is no way around that limitation of this validator.

This comment has been minimized.

@mxsasha

mxsasha Jun 6, 2015

Member

Yes. The only thing you could check later is an exact match, but that's much less likely to catch anything. I don't think it's worth the effort for such a tiny gain. Then again, the attributes that I expect to be most often used as a password are less often changed, like the user's name.

@mxsasha

mxsasha Jun 6, 2015

Member

Yes. The only thing you could check later is an exact match, but that's much less likely to catch anything. I don't think it's worth the effort for such a tiny gain. Then again, the attributes that I expect to be most often used as a password are less often changed, like the user's name.

requires the minimum length to be nine characters, instead of the default
eight.
* ``CommonPasswordValidator``, which checks whether the password occurs in a
list of common passwords. By default, it compares to an included list of

This comment has been minimized.

@carljm

carljm Jun 5, 2015

Member

"an included list of the 1000 most common passwords."

Or if that's too strong a claim, then "most" should be removed: "an included list of 1000 common passwords."

@carljm

carljm Jun 5, 2015

Member

"an included list of the 1000 most common passwords."

Or if that's too strong a claim, then "most" should be removed: "an included list of 1000 common passwords."

@carljm

This comment has been minimized.

Show comment
Hide comment
@carljm

carljm Jun 5, 2015

Member

This is great! Very excited to have this in Django 1.9; I think I'm about to backport it into a 1.8 project I'm working on currently :-) Thanks for working on it!

Member

carljm commented Jun 5, 2015

This is great! Very excited to have this in Django 1.9; I think I'm about to backport it into a 1.8 project I'm working on currently :-) Thanks for working on it!

@carljm

This comment has been minimized.

Show comment
Hide comment
@carljm

carljm Jun 5, 2015

Member

Of the comments I just left, the only one I would consider a merge blocker is the vague error message issue.

Member

carljm commented Jun 5, 2015

Of the comments I just left, the only one I would consider a merge blocker is the vague error message issue.

@alexbecker

This comment has been minimized.

Show comment
Hide comment
@alexbecker

alexbecker Jun 21, 2015

Contributor

Is there a reason why password validation is not performed on UserCreationForm?

Contributor

alexbecker commented Jun 21, 2015

Is there a reason why password validation is not performed on UserCreationForm?

@timgraham

This comment has been minimized.

Show comment
Hide comment
@timgraham

timgraham Jun 22, 2015

Member

This was merged in 1daae25.

Member

timgraham commented Jun 22, 2015

This was merged in 1daae25.

@timgraham timgraham closed this Jun 22, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment