Freelancing for Pale Blue

Looking for flexible work opportunities that fit your schedule?

Quickly add 2FA (email) for your custom Django admin

Django Apr 19, 2024

Keeping your Django admin panel safe is crucial. Regular passwords are good, but adding another layer of security is even better. That's where Two-Factor Authentication (2FA) comes in.

Just for clarity, I will repeat why 2FA is so important, even if it's a bit more inconvenient. If someone guesses/steals your password (the first lock), they still can't get in without the code from your authenticator app / email / hardware key (the second lock). This makes it much harder for attackers to break into your admin panel.

This post is the fastest guide for adding 2FA (with email) to your Django admin - especially if you're using a custom admin interface and the instructions in other blog posts are not working. I prefer email, and not an authenticator app since it's way easier to get started without requiring any additional new equipment/app.

Get started

We will use the battle-tested django-otp project. The project supports many types of authenticators (such as authenticator apps, hardware keys, etc) so make sure to check out the documentation to add additional methods of authenticating if needed.

pip install django-otp


Head to your and make the following modifications:

    # [...]

    # [...]
    # BELOW AuthenticationMiddleware!

Now somewhere, probably in you are defining your custom admin panel. Replace the base class with the OTP one (for the login screen to be replaced automatically with the one asking for the 2FA).

class CustomAdminSite(AdminSite):
    # [...]

class CustomAdminSite(OTPAdminSite):
    # [...]

admin_site = CustomAdminSite(name="myadmin")

The final step, in your register the model for registering email as 2FAs for your users. Important to note here, that this registration should not be in the same file that you are defining the custom admin class since it will create circular dependencies.

# Placed here (and not in custom_admin/ to avoid circular import
admin_site.register(EmailDevice, EmailDeviceAdmin)

Now run the migrations and you are ready to use it.

python migrate

Please note that the emails that will be sent, will be using Django's email configuration.


When you go to your admin site, you will be greeted with 3 input fields: username/email, password, and OTP. To get access to actually set up 2FA for your users, you need a one-time password. This is what the opt_static app you installed above is doing. To generate a static one-time code run the following command (remember, you can only use once this code):

python addstatictoken my_username

Use this to log in, and head to EmailOTP model to set up the 2FA email for each user. Congratulations, your admin site is now protected with an additional authentication layer :)

Happy coding!


Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.