Implementing¶
Users can opt-in to enhanced security by enabling two-factor authentication. There is currently no enforcement of a policy, it is entirely optional. However, you could override this behaviour to enforce a custom policy.
Limiting access to certain views¶
For increased security views can be limited to two-factor-enabled users. This allows you to secure certain parts of the website. Doing so requires a decorator, class mixin or a custom inspection of a user’s session.
Decorator¶
You can use django-otp’s built-in otp_required()
decorator to limit access to two-factor-enabled users:
from django_otp.decorators import otp_required
@otp_required
def my_view(request):
pass
Mixin¶
The mixin OTPRequiredMixin
can be used to
limit access to class-based views (CBVs):
class ExampleSecretView(OTPRequiredMixin, TemplateView):
template_name = 'secret.html'
Custom¶
The method is_verified()
is added through django-otp’s
OTPMiddleware
which can be used to check if the
user was logged in using two-factor authentication:
def my_view(request):
if request.user.is_verified():
# user logged in using two-factor
pass
else:
# user not logged in using two-factor
pass
Enforcing two-factor¶
Forcing users to enable two-factor authentication is not implemented. However, you could create your own custom policy.
Admin Site¶
By default the admin login is patched to use the login views provided by this
application. Patching the admin is required as users would otherwise be able
to circumvent OTP verification. See also TWO_FACTOR_PATCH_ADMIN
.
Be aware that certain packages include their custom login views, for example
django.contrib.admindocs. When using said packages, OTP verification
can be circumvented. Thus however the normal admin login view is patched,
OTP might not always be enforced on the admin views. See the next paragraph
on how to do this.
In order to only allow verified users (enforce OTP) to access the admin pages,
you have to use a custom admin site. You can either use
AdminSiteOTPRequired
or
AdminSiteOTPRequiredMixin
. See also the Django
documentation on Hooking AdminSite instances into your URLconf.
If you want to enforce two factor authentication in the admin and use the
default admin site (e.g. because 3rd party packages register to
django.contrib.admin.site
) you can monkey patch the default AdminSite
with this. In your urls.py
:
from django.contrib import admin
from two_factor.admin import AdminSiteOTPRequired
admin.site.__class__ = AdminSiteOTPRequired
urlpatterns = [
path('admin/', admin.site.urls),
...
]
Signals¶
When a user was successfully verified using a OTP, the signal
user_verified
is sent. The signal includes the
user, the device used and the request itself. You can use this signal for
example to warn a user when one of his backup tokens was used:
from django.contrib.sites.shortcuts import get_current_site
from django.dispatch import receiver
from two_factor.signals import user_verified
@receiver(user_verified)
def test_receiver(request, user, device, **kwargs):
current_site = get_current_site(request)
if device.name == 'backup':
message = 'Hi %(username)s,\n\n'\
'You\'ve verified yourself using a backup device '\
'on %(site_name)s. If this wasn\'t you, your '\
'account might have been compromised. You need to '\
'change your password at once, check your backup '\
'phone numbers and generate new backup tokens.'\
% {'username': user.get_username(),
'site_name': current_site.name}
user.email_user(subject='Backup token used', message=message)
Show OTP Secret Key During Setup¶
Users who only have a smartphone will have difficulty scanning the QR code
during setup. You can directly show the secret key within the QR code in text
form during setup by providing your own two_factor/core/setup.html
template
and using the secret_key
context variable.