Add Two Factor Authenication in Django Admin

2FA in Admin Page heyylateef | Nov 06 2023

Application security is important. With increasing number of threats over the internet, its a great idea to upgrade the security of your Django site. Most users use the Django-admin to do various administrative actions. Having a password isn't enough to protect your admin portal, lets use add a OTP (one-time-password) function to our admin using the TOTP (timed-one-time-password) method with the help of an authenticator app (such as Google Authenticator or Microsoft Authenticator).


In this tutorial we're going to:

  1. Create Django project
  2. Install 3rd party packages and edit settings.py
  3. Configure the first TOTP device for superuser
  4. Override Django's default admin to use our custom admin

1. Create Django Project



You'll need to create a folder for our project (Note: Use a virtual environment such as venv or conda. This will separate). Create a folder on your desktop, call it django2faTutorial. In terminal/CMD, enter the following:

$ cd django2fatutorial #changes directory
$ django-admin startproject 2fatutorial #creates a directory titled "2fatutorial". This is your Django project

 Once the Django project has been created, open the folder titled 2fatutorial



2. Install 3rd party packages

Inside your terminal/CMD, type in the following:

$ pip install django_otp qrcode

After installation, open  2fatutorial/settings.py. Scroll down to the INSTALL_APPS and add the following:

INSTALLED_APPS = [
...
'django_otp', #TOTP support
'django_otp.plugins.otp_totp', #TOTP support
]


Next, add the following to the MIDDLEWARE. Note: Make sure to put it after the django.contrib.auth.middleware.AuthenicationMiddleware:

MIDDLEWARE = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django_otp.middleware.OTPMiddleware', #TOTP
...

]



3. Configure the first TOTP device for superuser

Now lets create our super user. Inside your terminal/CMD, type in the following:

$python manage.py createsuperuser

Follow the prompt to create your superuser, we'll connect a TOTP device to it later.

We're going to use the django-otp package to create an TOTP device inside the default Django admin. Doing so, we can setup the superuser. Any other user added from now on can add a TOTP device by asking the superuser to connect a device. Inside of 2fatutorial/urls.py, copy and paste the following:

from django.contrib import admin
from django.urls import path, include

from django.contrib.auth.models import User
from django_otp.admin import OTPAdminSite
from django_otp.plugins.otp_totp.models import TOTPDevice
from django_otp.plugins.otp_totp.admin import TOTPDeviceAdmin

class OTPAdmin(OTPAdminSite):
pass

admin_site = OTPAdmin(name='OTPAdmin')
admin_site.register(User)
admin_site.register(TOTPDevice, TOTPDeviceAdmin)

urlpatterns = [
path('admin/', admin.site.urls),
]


Run migrations:

$python manage.py migrate

Run the server:

$python manage.py runserver

Open the admin page and login using your superuser credentials: http://localhost:8000/admin

Now you should see "OTP_TOTP" in your admin site. Click "Add"


Inside of the "Add TOTP device" form, use the magnifying glass to search for your user. Give the TOTP device a name, and set "Tolerance" to at least 90. You may leave all other settings as default. At the bottom of the form, click "Save".


You should now see the name of the TOTP device you just created. Lets now connect it to a authenticator app (like Google Authenticator or Microsoft Authenticator). Click on "qrcode". You should see a qr code that you can scan with your authenticator app. Scan it.




4. Override Django default admin with OTPAdmin

Lastly, the django-otp package conveniently has a custom admin page that works just like the default admin page, except that it enforces the OTP (2FA) on the admin page. Lets override the default admin class to use the OTPAdmin. Inside your project, create 2 new files: admin.py and apps.py.

For admin.py, copy and paste the following:

from django.contrib import admin
from django.contrib.auth.models import User
from django_otp.admin import OTPAdminSite
# from django_otp.plugins.otp_totp.models import TOTPDevice
# from django_otp.plugins.otp_totp.admin import TOTPDeviceAdmin

class OTPAdmin(OTPAdminSite):
pass


For apps.py, copy and paste the following:

from django.contrib.admin.apps import AdminConfig


class MyAdminConfig(AdminConfig):
default_site = "2fatutorial.admin.OTPAdmin"


Lastly, go to settings.py and edit in your new admin config into the INSTALLED_APPS:

INSTALLED_APPS = [
...
#'django.contrib.admin',
"2fatutorial.apps.MyAdminConfig", #replaces django.contrib.admin
...
]


Save all files and run the server again, and go to the admin page. You should be presented with this:


Go ahead and try to sign in using your superuser credentials and now your OTP from your authenticator app. By using overriding the default admin site, all of your app-based admin actions should also appear in your admin page!

About The Lab

Like the content posted on this site? Need help with another web project? Want to give some feedback? Feel free to contact me via email or social media!

Know more!
DigitalOcean Referral Badge