Here comes the concluding part of this series. In this part, we'll focus on extending the registration flow of the third-party application we have been using to implement the specifications we want for our app.
NOTE: This section is optional and as a result, it was not included in this tutorial's github repository. The feature was also not incorporated in its live version
The specification we'll be addressing says that if a user fails to identify himself/herself using his/her device's authenticator or external authenticator(s) supported by python-fido2, such user should be removed from the database, logged out of the application and then redirected to the registration page to restart the process. This is to ensure that only verified users who used the supported attestation formats during registration are authenticated and authorized.
Unfortunately, django-mfa2 was not built to support that out-of-the-box. However, to add this feature, one needs to have a local version of the application to be able to extend its functionalities.
Going by the idea stated above, we need to move the mfa
package which should be located in site-packages
directory of your virtual environment folder. The path to mine is django-mfa-example/env/lib/python3.8/site-packages
.
It should be noted that you may not be able to get this path if you used pipenv
for your virtual environment. One option you have, in this case, is to download the mfa application and move it to your application directory.
Now to the codes. A careful inspection of mfa's source code reveals that most of the redirections, in case of failure, can be intercepted in the script
section of the FIDO2/Add.html
file located in its templates
directory. We'll be modifying line 37 and line 40.
First, to address removing and logging out users, append this function to your accounts/views.py
file:
def remove_user_and_redirect(request):
User.objects.filter(username=request.user.username).delete()
logout(request)
messages.error(request, f'Your fingerprint capture was not valid. Kindly re-register and try again.')
return redirect(reverse('accounts:register'))
This simply fetches out the user using its username and deletes it from the database using Django ORM's delete()
method. Then, such a user will be logged out using one of Django's auth methods, logout
. An error message will then be flashed to inform the user of the action taken and finally, redirected to the registration page.
Add this view function to your accounts/urls.py
.
...
urlpatterns = [
...
path('remove_user_and_redirect', views.remove_user_and_redirect, name='remove_user_and_redirect'),
]
Now, proceed to the lines pointed out earlier (line 37 and line 40) and append the following:
...
else{
...
setTimeout(function () {
window.location.href = "{% url 'accounts:remove_user_and_redirect' %}" }, 1000);
}
to each of the lines.
There is nothing much here. We just instruct the app to wait for about 1000ms
so that the user can read the error message outputted and then redirect automatically by calling the function added above through the url, accounts:remove_user_and_redirect
. setTimeout() method executes a function or specified piece of code once the timer expires.
Hurray!!! We have come to the end of this rather long piece. Hope you learned something.
Do you have any suggestions, comments or reactions? Kindly drop them in the comment section below. Let's keep learning and practising.
Outro
Enjoyed this article? I'm a Software Engineer and Technical Writer actively seeking new opportunities, particularly in areas related to web security, finance, healthcare, and education. If you think my expertise aligns with your team's needs, let's chat! You can find me on LinkedIn and Twitter.
If you found this article valuable, consider sharing it with your network to help spread the knowledge!
Top comments (3)
Hello,
I have managed to install your app on centos 8 stream.
I am clicking on registration link but I am getting error:
Registeration Failed as TypeError: Cannot read properties of undefined (reading 'create')
The only changes done was removing from accounts\utils.py
if not username.isalnum():
return False
The login works with any username regardless of registration. No MFA fingerprint scan so far.
Thank you !
I have managed to fix that problem by going in production mode (https).
Now I have another issue.
I am registering the fingerprint all ok. But login works with any fingerprint. I'll debug more the login part but I guess it should work.
Sorry, which kind of fingerprint I can use to register and authenticate user in my Django project?