Exception classes and error handling#
Because pwned-passwords-django
communicates with a remote API, it can
encounter problems, such as connection failures, connection timeouts, failures
of the Pwned Passwords API, and so on.
Exceptions raised in communicating with Pwned Passwords will be caught and translated into instances of:
- exception pwned_passwords_django.exceptions.PwnedPasswordsError[source]#
A wrapper for all exceptions raised in communicating with Pwned Passwords.
Has the following attributes:
- code#
A short code indicating the type of error.
The code
attribute uses the following enum:
- class pwned_passwords_django.exceptions.ErrorCode[source]#
- API_TIMEOUT#
An HTTP request to the Pwned Passwords API timed out.
- HTTP_ERROR#
An HTTP request to the Pwned Passwords API returned an error (4XX or 5XX) status code.
- REQUEST_ERROR#
Another type of error occurred in performing the request to the Pwned Passwords API.
- UNKNOWN_ERROR#
An unanticipated or unknown type of error occurred, possibly in code in
pwned-passwords-django
. This can happen if, for example, the Pwned Passwords API begins returning responses in a different format than expected and so parsing of the response fails.
How errors are handled#
When the PwnedPasswords
client class
encounters a situation that requires raising a PwnedPasswordsError
, it
will emit a log message of log level logging.ERROR
prior to raising the
exception. It will also raise the exception “from” the parent exception it
encountered, such as an httpx.TimeoutException
or
httpx.HttpStatusError
. If you are working directly with an instance of
PwnedPasswords
or a customized subclass of
it, your code is responsible for catching and handling any
PwnedPasswordsError
it raises.
When other parts of pwned-passwords-django
encounter a
PwnedPasswordsError
raised from the client, they will behave as follows:
The password validator will catch the exception, log a message of log level
logging.ERROR
and fall back to using Django’sCommonPasswordValidator
, which has a smaller (approximately 20k passwords) but locally-stored list of common passwords.The middleware will catch the exception, log a message of log level
logging.ERROR
, and fall back to Django’sCommonPasswordValidator
.The
check_password()
andcheck_password_async()
functions will not catch exceptions for you; your code is responsible for catching and handling exceptions raised from them.
Filtering sensitive information#
Because pwned-passwords-django
works with values that are (or, in the case
of the middleware, are likely to be) passwords or password-like credentials,
care must be taken to avoid accidentally exposing those values in their raw
form. This can easily happen by accident, for example, if an exception occurs
while trying to check a password, since the password will usually be a local
variable of the stack frame where the exception was raised, and thus is
available from inspecting the traceback. Or a password might accidentally find
its way into the message of an exception.
Django provides some tools to filter sensitive information from error reports,
and it is strongly recommended that if you write code which interacts with
pwned-passwords-django
directly – for example, via the API –
you take care to use those tools.
Internally, pwned-passwords-django
takes the following measures:
The
validate()
method of the validator is decorated withsensitive_variables()
which will filter all of its local variables from Django’s default logging and error reporting.The internal helper functions of the middleware which actually scan the request payload for likely passwords are decorated with
sensitive_variables()
.The
check_password()
andcheck_password_async()
functions pass through to methods of the same name on an instance ofPwnedPasswords
, which are decorated withsensitive_variables()
.The error handling in
PwnedPasswords
, when it encounters an unknown/expected exception type, performs minimal logging of the exception’s details. Only the class name of the caught exception will be logged, not its associated message or other arguments.
This approach can make debugging errors more difficult, but such difficulty is generally preferable to accidental exposure of passwords via error-reporting tools.