Hello all,

I've taken another stab at 16860[1]: having a password validation/policy in 
Django. I've made an initial simple PR[2] to show the approach I'd like to use 
- no tests or documentation yet, the example validators are not very nice, 
possibly bad naming, etc. But this should be sufficient to show how I would 
like to tackle this. There's quite a few decisions to take, influencing the 
later possibilities, which I'll try to outline below.

Users choosing awful passwords is a serious security issue. Although password 
validation can only go so far - especially to the extent that we can implement 
in Django itself - to me it seems part of our responsibility in helping Django 
developers to build safer websites.

First, let me briefly describe my approach: we add a new setting to define zero 
or more password validator classes. Optionally, a class can be provided with 
custom arguments to it's constructor. Each validator class has a help_text() 
method and a validate(password, user) method. The former produces a 
translatable sentence to be included in the form field's help text. The 
validate method validates a certain password, optionally taking the context of 
a user into account and passes its judgement on the password. If a validator 
considers a password insufficient, it raises a ValidationError.

This is tied to the validation and form field setup in SetPasswordForm and 
AdminPasswordChangeForm. An obvious choice seems to be to tie this to 
User.set_password(). However, I intentionally did not include that step, as I 
feel this validation should primarily take place on the user frontend site with 
forms. This mirrors the way we typically handle this in Django. Should someone 
feel different, and want to tie this to set_password() as well, this is 
possible with a custom user object. Tying this validation into any other place 
is also trivial: just adding a single line.

I decided not to go for standard Django validators, as I felt this would offer 
insufficient flexibility and configurability - as was already raised in 
previous discussions on this issue.

In the ticket, Shai described a few particular goals for this feature:

- Informing the user of the various password requirements: this is possible by 
each validator providing a description, which can be dependent on it's 
configuration, of it's requirements. Independent sentences from different 
validators are now concatenated, an approach which will not always yield the 
prettiest language.
- Allowing policies to chain together smoothly: multiple validators can be run 
sequentially, stopping after the first failure.
- Provide flexibility for complex requirements (some may include their own 
models): this is entirely possible within the design.
- Backwards compatibility: the default setting is to have no validators, which 
means no change and no modifications in help text. I do suggest we include some 
reasonable defaults in the standard project template.
- Javascript validation assistance or HTML5 support: not implemented currently, 
but this could be added in a similar way as help texts.
- Prevent using email, username or other user attributes as (part of) 
passwords: where possible, the user object is passed to the validator. There's 
a (not pretty) example of this in the PR.
- Prevent reuse of old passwords: it is possible in the design for a validator 
to store all passwords it saw. I have doubts on whether this would be a good 
approach though.

So I think this design makes it simple to have sane defaults for new projects, 
extensive configurability while keeping simple scenarios simple to configure, 
and easy extensibility with third party password validators (zxcvbn comes to 
mind). I'd love to hear any feedback and ideas you may have.

Erik


[1] https://code.djangoproject.com/ticket/16860
[2] https://github.com/django/django/pull/4276

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/DC7E0945-5FC9-43CA-97C5-FE5872A05DE1%40solidlinks.nl.
For more options, visit https://groups.google.com/d/optout.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to