Two Factor authentication in Django Admin
By: Anas Ahmed
Tags: Django, Django Admin

Two Factor authentication in Django Admin

Django is shipped with numerous “batteries included” tools that one can utilize to concise and his/her code and at the same time speed up their development. One such tool or rather “app” in technical term, that Django offers, is “Django admin”.

Django admin is such a powerful tool that provides you almost any type of operations on models from CRUD (Create-Read-Update-Delete) to filtering, searching and sorting capabilities on just a few keystrokes. No doubt about the robustness of Django admin, but when it comes to customizing the behavior of the admin out of the way, it sometimes gives you excruciating pain and becomes a nightmare that you probably would never want to think about it again.

In one of our project we have been assigned a task to secure our Django admin with two factor authentication in order to meet some weird abbreviated country compliance. At that time we had no clue of how to implement this functionality and unfortunately there was not much help available on the internet. We heard of Django support for custom admin site but never tried it before. So after successfully found the solution, my fellow developer and mentor motivated me to write an article about it.

First of all we inherit our class from admin.AdminSite in order to make our own customize AdminSite (depending on your need you can use monkey patching to swap methods in original AdminSite class, you don’t need to create different AdminSite class). Following after we override login method, we change nothing from the original method except for the last line, where instead of calling to LoginView we call our CustomLoginView.

Custom AdminSite Class

Our CustomLoginView which ultimately inheriting functionalities from Django LoginView except for the few changes. We override two methods of LoginView: get_success_url and form_valid.

form_valid is called after Django validates our form and finds no error otherwise form_invalid is called by Django. get_success_url as the name suggest, redirects users to certain view if form data is valid.

CustomLoginView Class

After admin is authenticated successfully from the first view we redirect it to our OTPLogin view, where admin must enter the otp code that is send to him/her via email from the previous view. If the otp code is correct then admin is permitted to view the dashboard(admin panel) otherwise he or she is redirected back to the previous view i.e CustomLoginView.

AdminOTPAuthentication Class

OTPAuthenticationForm

login_otp.html

Our AdminOTPAuthenticationView is inherited from Django FormView. We override the following methods: get_success_url, get_context_data, form_valid and form_invalid.

I explained the purpose of most of these methods above except for get_context_data which you need when you want to pass some extra data to template. I utilized it for passing redirection parameter to login_otp.html template. The login_otp.html extends from admin/base_site.html.

One last thing, the login function which is called inside form_valid method creates persistent session for the particular user. You can find it at django.contrib.auth.login.

I hope you would enjoy reading this article.