feat(2fa): implement two-factor authentication - #3207
Open
FrankApiyo wants to merge 20 commits into
Open
Conversation
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
from
August 11, 2026 07:34
820f5f4 to
47ec239
Compare
This was referenced Aug 11, 2026
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
from
August 11, 2026 09:15
6fa06dc to
47ec239
Compare
2 tasks
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
3 times, most recently
from
August 14, 2026 14:48
808a0ff to
53f57b8
Compare
2 tasks
FrankApiyo
marked this pull request as ready for review
August 17, 2026 12:04
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
3 times, most recently
from
August 19, 2026 11:10
7532dd9 to
d29ef14
Compare
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
2 times, most recently
from
August 19, 2026 13:11
5a1adfb to
4042f52
Compare
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
2 times, most recently
from
August 20, 2026 10:00
9cd079d to
7a0b620
Compare
FrankApiyo
force-pushed
the
feat/django-two-factor-auth
branch
from
August 20, 2026 12:22
7a0b620 to
46c4cba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes / Features implemented
Two-factor authentication moves into onadata. Login runs through the wizard at
/account/login/for everyone, and/accounts/login/redirects to it rather than rendering a password-only form beside it. Enrolment stays off until a deployment setsENABLE_TWO_FACTOR./api/v1/totp/:status,enroll/start,enroll/confirm,disable,verify,recovery/generate,recovery. Anything that weakens or replaces a factor needs a current code, or a grantverifyminted for that one operation. Responses carryCache-Control: no-store.TWO_FACTOR_ENROLMENT_REQUIRES_PASSWORD, off by default because a deployment whose users authenticate elsewhere may hold hashes nobody knows.two_factor_urls.py.Also:
is_ownerresolvesLOGIN_URL, which is a URL name now;django-two-factor-auth,django-otpandqrcodebecome declared dependencies rather than deployment-only ones;pyproject.tomlstops ruff and isort reordering imports against each other; and two existing tests stop hard-coding/accounts/login.Steps taken to verify this change does what is intended
Tests are driven through the wizard's own POSTs rather than against the forms, with codes from a real HOTP implementation — patching
verify_tokenwould pass against a device no authenticator app agrees with. Code verification is covered byTransactionTestCaseconcurrency tests, since the race they guard needs committed data on a second connection.Exercised by hand against a running stack: enrol, sign in with a code, and sign in as a user with no factor.
Side effects of implementing this change
django.contrib.adminis safe: the library redirects/admin/login/toLOGIN_URL. Reaching/admin/still needs only staff permission, so a staff user who has not enrolled gets in on a password alone.Before submitting this PR for review, please make sure you have:
Closes #