Django application to quickly provide you with TOTP with recovery codes right out of the box.

New ticket tracker added

3 years ago

New mailing list added

3 years ago

#django-nlotp nlshield

Django application to quickly provide you with TOTP with recovery codes right out of the box.

Version: 0.1

Project Links: Issues - Mailing List - Contributing

Author: Netlandish (https://www.netlandish.com)

#Netlandish One-Time Password (Two-Factor Authentication)

The Django app django-nlotp (Netlandish OTP) that provides ready to use views to setup TOTP support as well as recovery codes in your project. It's basically views and a middleware that operates with the django-otp (GitHub) app, which does the heavy lifting.

We created this because we use django-otp in several products as well as client projects. After using it twice in a very similar fashion we knew we needed to write an app that we can plug in to virtually any product and immediately have access to OTP support.

This app should give you everything you need to quickly implement OTP in your project. You can use settings for both django-nlotp and django-otp apps to customize as you wish. This app should give you coverage for the majority of use cases you have. If you want to get deeper into the weeds then we'd recommend rolling your own custom approach direct with django-otp.

#What is Two-Factor Verification?

Two Factor Verification (2FA) makes your account more secure by requiring two things in order to log in: something you know and something you own.

#How does it work?

"Something you know" is your username and password, while "something you own" can be an application to generate a temporary code.

Users who have chosen to set up 2FA will be asked to provide their second method of identity verification during the log in process.

#How does 2FA with an authentication application (TOTP) work?

Users can set up 2FA using any authentication application that supports the TOTP standard.

TOTP authentication applications generate a regularly changing authentication code to use when logging into your account.

Because TOTP is an open standard, there are many applications that are compatible with your AnyHow account. Popular applications include:

There are many others as well.

#User Verification

By default in django-nlotp the user verification process (when the user is to enter their one time password) will check the password submitted in the following order:

  1. Check for a TOTP device match. In other words, check that the code matches the configured user device.
  2. If it doesn't match, then it checks if the code is a user's backup code. If so, it allows the user access and removes the provided code from future use.


  • Add django_otp, django_otp.plugins.otp_totp, django_otp.plugins.otp_static and nlotp to INSTALLED_APPS. For example:

  • Add nlotp.middleware.OTPCheckMiddleware to MIDDLEWARE. It must be installed after django.contrib.auth.middleware.AuthenticationMiddleware. For example:

  • Add nlotp urls to urls.py. For example:
urlpatterns = [
         path('otp/', include('nlotp.urls', namespace='nlotp')),



Verify page url, user is redirected to this page after login if has 2FA enabled. Defaults to nlotp:verify-otp url.


List of urls excluded from redirect to NLOTP_VERIFY_URL if logged in user has 2FA enabled but is not verified. Defaults to (NLOTP_VERIFY_URL,). You should include your app login and logout urls in this list, for example include in your settings:



If 2FA setup is mandatory. Logged in user is forced to setup 2FA, redirected to NLOTP_2FA_SETUP_URL. Defaults to False.


2FA setup page url, where OTP setup is done (enable/disable and code generation). Defaults to nlotp:two-factor-auth url.


User TOTP device QR code generation url, returns a QR code SVG image. Defaults to nlotp:qr-code url.


List of urls excluded from redirect to NLOTP_2FA_SETUP_URL when NLOTP_2FA_SETUP_REQUIRED is enabled and user has not setup 2FA. Defaults to (NLOTP_2FA_SETUP_URL, NLOTP_QR_CODE_URL). You should include your app login and logout urls in this list, for example include in your settings:



django-otp setting, this is how your app will be shown in the auth app (e.g. Google Authenticator). Defaults to None. It can be string or a callable. For example:

def totp_issuer(device):
    return f'Your app name ({device.user.email})'

OTP_TOTP_ISSUER = totp_issuer

Refer to django-otp documentation for more details.


There are 2 basic templates provided with the app, that you should consider to override.


Verify page template.

#Context variables
  • form: customized version of django-otp OTPTokenForm; otp_device and otp_token fields should be included the template.


2FA setup page template.

#Context variables
  • form: user model form that includes authentication_code field (should be included in template if 2FA is disabled for user) and password (should be included in template if 2FA is enabled for user).

  • totp_device: user TOTPDevice, it could be confirmed (2FA enabled) or not (2FA disabled).

  • static_device: user StaticDevice, it could be confirmed (2FA enabled) or not (2FA disabled).

  • show_codes: if backup codes (static device) should be shown, it's set to True after user enables 2FA or requests new backup codes.

  • qr_code_url: NLOTP_QR_CODE_URL url.

  • setup_required: NLOTP_2FA_SETUP_REQUIRED flag.



Gets user TOTPDevice or creates a new one (not confirmed).


Gets user StaticDevice or creates a new one (not confirmed). Adds 10 new backup codes if created.


Adds count (10 by default) backup codes to user StaticDevice.



Simple mixin that inserts logged in user TOTP device in view context.


We accept patches submitted via hg email which is the patchbomb extension included with Mercurial.

Please see our contributing document for more information.

The mailing list where you submit your patches is ~netlandish/public-inbox@lists.code.netlandish.com. You can also view the archives on the web here:


To quickly setup your clone of django-nlotp to submit to the mailing list just edit your .hg/hgrc file and add the following:

to = ~netlandish/public-inbox@lists.code.netlandish.com

flagtemplate = "django-nlotp"

git = 1

We have more information on the topic here:

All documentation, libraries, and sample code are Copyright 2020 Netlandish Inc. (https://www.netlandish.com). The library and sample code are made available to you under the terms of the BSD license which is contained in the included file, BSD-LICENSE.

#Commercial Support

This software, and lots of other software like it, has been built in support of many of Netlandish's own projects, and the projects of our clients. We would love to help you on your next project so get in touch by dropping us a note at hello@netlandish.com.