One-time Passwords (OTP)

The otp extra provides support for one-time passwords (OTP) in HIdP. This allows users to enable two-factor authentication (2FA) for their accounts.

Note

OTP support in HIdP is based on django-otp.

Installation

OTP support in HIdP is included in the recommended extra. To install the recommended extra, use the following command:

pip install django-hidp[recommended]

See Installation Extras for more information on available extras.

Configuration

To enable OTP support in HIdP, the following needs to be added to the Django settings:

INSTALLED_APPS = [
    ...,
    'django_otp',
    'django_otp.plugins.otp_totp',
    'django_otp.plugins.otp_static',
    'hidp.otp',
    ...
]

MIDDLEWARE = [
    ...,
    # Add the OTP middleware to the middleware list, after 
    # the session and authentication middleware
    'django_otp.middleware.OTPMiddleware',
]

Important

The configuration above does not enable OTP verification on login just yet. Read the following sections to learn how to enable OTP verification for users.

Usage

After enabling OTP support in HIdP, users can enable two-factor authentication (2FA) for their accounts. Whether users are required to verify or enable 2FA can be configured by enabling one or more OTP Policies.

OTP Policies are used to configure the requirements for OTP verification. Site-wide policies are implemented as Django middleware, while view decorators can be used to apply policies to specific views.

Note

These sections use the same terminology as the Django-OTP documentation. For more details, refer to the Django-OTP glossary.

Available OTP Policies

Site-wide Policies

The following site-wide OTP policies are available. To enable a policy, add the middleware to the MIDDLEWARE list in the Django settings, after the django_otp.middleware.OTPMiddleware middleware.

hidp.otp.middleware.OTPRequiredMiddleware

Requires users to verify their OTP before accessing any view (that is not exempt using the otp_exempt decorator). This is the strictest policy: users must verify their OTP before they can access any part of the site, which also means that if they haven’t set up OTP yet, they will be redirected to the OTP setup view upon first login.

hidp.otp.middleware.OTPVerificationRequiredIfConfiguredMiddleware

Requires users to verify their OTP if they have configured OTP. This policy is less strict than OTPRequiredMiddleware because it allows users to access the site without verifying their OTP if they haven’t configured OTP yet.

hidp.otp.middleware.OTPSetupRequiredIfStaffUserMiddleware

Requires staff users to set up and verify their OTP before accessing any view. This policy is useful for enforcing OTP setup for staff users, while allowing non-staff users to access the site without setting up OTP.

Warning

This policy does not enforce other users that have OTP set up are required to verify their OTP. Also add OTPVerificationRequiredIfConfigured middleware in order to do so.

View Decorators

The following view decorators can be used to apply OTP policies to specific views:

django_otp.decorators.otp_required

Requires users to verify their OTP before accessing the view. See the Django-OTP documentation for more information.

hipd.otp.decorators.otp_exempt

Exempts users from verifying their OTP when accessing the view, even if a site-wide policy (middleware) requires OTP verification.

Examples

You can combine multiple policies by adding multiple middleware classes to the MIDDLEWARE list in the Django settings. For example, to make OTP required for staff users and optional for non-staff users, you can use the following configuration:

MIDDLEWARE = [
    ...,
    'django_otp.middleware.OTPMiddleware',
    'hidp.otp.middleware.OTPSetupRequiredIfStaffUserMiddleware',
    'hidp.otp.middleware.OTPVerificationRequiredIfConfiguredMiddleware',
    ...
]

If you have certain views that should be exempt from OTP verification, you can use the otp_exempt decorator:

from hidp.otp.decorators import otp_exempt

@otp_exempt
def my_view(request):
    # This view can be accessed without verifying OTP  
    ...


# Or, on a class-based view:
from django.utils.decorators import method_decorator
from django.views.generic import View

@method_decorator(otp_exempt, name='dispatch')
class MyView(View):
    ...

Customizing OTP Policies

You can create custom OTP policies by subclassing the hidp.otp.middleware.OTPMiddlewareBase class and implementing the user_needs_verification method. This method should return True if the user needs to verify their OTP, and False otherwise. The method may assume the user is authenticated and not yet verified.

For example, to create a policy that requires OTP verification for users with a specific group, you can create a custom middleware class like this:

from hidp.otp.middleware import OTPMiddlewareBase

class OTPRequiredForGroupMiddleware(OTPMiddlewareBase):
    def user_needs_verification(self, user):
        return user.groups.filter(name='RequireOTP').exists()

See the source code of the hidp.otp.middleware module for more examples of custom OTP policies.