The password-checking middleware¶
To help with situations where a potentially-compromised password is used
in ways Django’s password validators won’t catch, pwned-passwords-django also provides a middleware
which monitors every incoming HTTP request for POST payloads which appear
to contain passwords, and checks them against Pwned Passwords.
- pwned_passwords_django.middleware.pwned_passwords_middleware(get_response: Callable) Callable[source]¶
Factory function returning a middleware – sync or async as necessary – which checks
POSTsubmissions that potentially contain passwords against the Pwned Passwords database.To enable the middleware, add
"pwned_passwords_django.middleware.pwned_passwords_middleware"to yourMIDDLEWAREsetting. This will add a new attribute –pwned_passwords– to eachHttpRequestobject. Therequest.pwned_passwordsattribute will be alistofstr.Warning
Middleware order
The order of middleware classes in the Django
MIDDLEWAREsetting can be sensitive. In particular, any middlewares which affect file upload handlers must be listed above middlewares which inspectPOST. Since this middleware has to inspectPOSTfor likely passwords, it must be listed after any middlewares which might change upload handlers. If you’re unsure what this means, just put this middleware at the bottom of yourMIDDLEWARElist.The
request.pwned_passwordslist will be empty if any of the following is true:The request method is not
POST.The request method is
POST, but the payload does not appear to contain a password.The request method is
POST, and the payload appears to contain one or more passwords, but none were listed as compromised in Pwned Passwords.
If the request method is
POST, and the payload appears to contain one or more passwords, and at least one of those is listed in Pwned Passwords, thenrequest.pwned_passwordswill be a list of keys fromrequest.POSTthat contained compromised passwords.For example, if
request.POSTcontains a key namedpassword_field, andrequest.POST["password_field"]is a password that appears in the Pwned Passwords database,request.pwned_passwordswill be["password_field"].Warning
API failures
pwned-passwords-djangoneeds to communicate with the Pwned Passwords API in order to check passwords. If Pwned Passwords is down or timing out (the default connection timeout is 1 second), or if any other error occurs when checking the password, this middleware will fall back to using Django’sCommonPasswordValidator, which uses a smaller, locally-stored list of common passwords. Whenever this happens, a message of levellogging.ERRORwill appear in your logs, indicating what type of failure was encountered in talking to the Pwned Passwords API.See the error-handling documentation for details.
Here’s an example of how you might use Django’s message framework to indicate to a user that they’ve just submitted a password that appears to be compromised:
from django.contrib import messages def some_view(request): if request.method == "POST" and request.pwned_passwords: messages.warning( request, "You just entered a password which appears to be compromised!" )
pwned-passwords-djangouses a regular expression to guess which items inPOSTare likely to be passwords. By default, it matches on any key inPOSTcontaining"PASS"(case-insensitive), which catches input names like"password","passphrase", and so on. If you use something significantly different than this for a password input name, specify it – as a string, not as a compiled regex object! – in the settingsettings.PWNED_PASSWORDS["PASSWORD_REGEX"]to tell the middleware what to look for. See the settings documentation for details.