It is a very common practice nowadays to keep alive signed in user sessions for a very long time. But some web pages
usually deal with sensitive information (such as billing information or change email forms) and it is a good idea to
ask the user to confirm his/her credentials. To achieve this task, we will be using the built-in check_password
and
the user’s last_login
field.
To illustrate a little bit more what we want to achieve, take the picture below as an example:
No redirects, we want to keep the current URL. Make it last for a few hours.
Building the Form
I’m using a User ModelForm to hold an instance of the logged in user. Basically I’m overriding the clean()
method
so to validate the informed password using the built-in function check_password
, where you can test a plain-text
password against its hash.
And in the same method, I’m updating the last_login
with the current time. This field will be used to control
when we should ask for the user’s password again.
The View Function
We will only need a view function (or a class-based view), there is no need for a url route.
views.py
Since we kept the same URL, simply return the current path on get_success_url()
to reload the page and let the user
move on.
confirm_password.html
The Decorator
The decorator will be responsible for checking if the application needs to ask the user to confirm his/her password. It will also make it easy to reuse across multiple views.
decorators.py
A few things here: I’m importing the ConfirmPasswordView
inside the wrapper class to avoid circular import. In the
datetime.timedelta(hours=6)
I’m defining that the application will ask for the user’s password if it’s been more than
6 hours since his/her last login.
We can extract the hardcoded 6 hours
later on.
Usage
With the form, the view and the decorator we should be good to go.
views.py
If there is more than six hours since the authentication, when the user tries to access the settings page, the
ConfirmPasswordView
will be rendered instead, using the settings URL.
Process the form, updates the user.last_login
:
That’s it. Now it is just a matter of decorating the views with @confirm_password
.