Package: django-mfa3
django-mfa3An opinionated Django app that handles multi factor authentication (MFA) via
FIDO2, TOTP, and recovery codes.FeaturesTwo factor authentication is required on login (if the user has registered a key)Stuff just works without much configurationThe UI allows to add new keys and to remove keys that have been compromisedYou can optionally enforce MFA for all usersYou can (and should) customize the templatesSimple code, few dependenciesInstallationpip install django-mfa3UsageAdd'mfa'toINSTALLED_APPSUsemfa.views.LoginViewinstead of the regular login view. (Be sure to
remove any other login routes, otherwise the multi factor authentication
can be circumvented. The admin login will automatically be patched to
redirect to the regular login.)SetMFA_DOMAIN = 'example.com'andMFA_SITE_TITLE = 'My site'Register URLs:path('mfa/', include('mfa.urls', namespace='mfa')The included templates are just examples, so you shouldreplace themwith your ownFIDO2 requires client side code. You can either implement it yourself or use the included fido2.js (in which case you will have to provide the third party librarycbor-js).Somewhere in your app, add a link to'mfa:list'Enforce MFAOptionally, you can add'mfa.middleware.MFAEnforceMiddleware'toMIDDLEWARE(afterAuthenticationMiddleware!). It will force users to setup two factor
authentication by redirecting all authenticated requests to'mfa:list'as
long as the user has no MFAKeys. You can usemfa.decorators.publicto add
exceptions.Send email on failed login attemptIf someone failes to login on the second factor that might indicate that the
first factor (password) has been compromised. django-mfa3 will automatically
send a warning to affected users under the following conditions:Django needs to beconfigured for sending emailThere must be an email address associated with the user accountYou need to provide some templatesmfa/login_failed_subject.txt: optional, a default is includedmfa/login_failed_email.txt: required, an example is included in thetestsmfa/login_failed_email.html: optionalAll templates have access to the following context data:email,domain,site_name,user,method.StatusI am not sure whether I will be able to maintain this library long-term. If you
would like to help or even take ownership of this project, please contact me!Related projectsdjango-mfa3 is based onpyotpandpython-fido2.It is inspired by but not otherwise affiliated withdjango-mfa2.
A big difference between the two projects is that django-mfa2 supports many
methods, while django-mfa3 only supports FIDO2 and TOTP. U2F was dropped
because it is now superseded by FIDO2. Email and Trusted Devices were dropped
because I felt like they have inferior security properties compared to FIDO2
and TOTP.Another major inspiration isdjango-otp. It is probably the most
mature library when it comes to two factor authentication in django. However,
itsbasic structure is not compatible with
FIDO2.It is recommended to use django-mfa3 withdjango-axesfor rate limiting. It is
also compatible withdjango-stronghold.Security considerationsThe actual cryptography is handled by pyotp and python-fido2. This library only
provides the glue code for django. Still, there could be issues in the glue.A notable attack surface is server state: The authentication consists of three
separate HTTP requests: The regular login, fetching a challenge, and a
response. The server keeps some state in the session across these requests. For
example, the user is temporarily stored in the session until the second factor
authentication is done. The logic for handling this state is not as straight
forward as I would like and there might be issues hidden in there.Please also be careful when implementing and using this library in your project
to prevent higher level security or usability issues. Please refer to other
guidelines like theOWASP Cheat Sheetfor more informaton on that topic.