Settings → Account: the second-factor card promises an authenticator app to passkey-only accounts, and a code \"Always\" on trusted browsers #428
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#428
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the Account page against allauth's MFA stages.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now ataccounts/settings_views.py:192(mfa_enabled); the template,accounts/stages.pyand the settings have not moved.The Two-factor authentication card on the Account page describes how sign-in is protected, and gets it wrong in two cases. An account whose only second factor is a passkey or security key is told it has an authenticator app. And every account with a second factor is told that a password sign-in asks for a code "Always", although a browser the person chose to trust is not asked for 30 days.
templates/settings/account.html:150-151and:166;accounts/settings_views.py:190, wheremfa_enabledisget_mfa_adapter().is_mfa_enabled(self.request.user)with no types;accounts/stages.py:18-20, the module docstring;config/settings/base.py:281-282,MFA_TRUST_ENABLED = TrueandMFA_TRUST_COOKIE_AGE = timedelta(days=30).is_mfa_enabled(user, types=None)is true for anyAuthenticatorrow, a WebAuthn key included. Somebody who has added only a passkey therefore reads "On. Signing in asks for a code from your authenticator app, or a recovery code." They have no authenticator app; after a password, allauth asks them for the key.AuthenticateStage._should_handle, whichSecondFactorStagecalls first, returnsFalsewhentrust.is_trusted_browser(request, user)is true, and the trust step is offered after every successful second factor (tests/test_mfa.py::test_a_trusted_browser_is_not_asked_againexercises exactly this). Thestages.pydocstring repeats the same "always".account.html:162-163); as written it produces that confusion, and it misstates to a person how their account is protected.is_mfa_enabled(user, [Authenticator.Type.TOTP])and keys frompasskeys.count(or a WebAuthn filter), and word the status for each case: an app, a key, or both. Reword the password line to say the second factor is asked for unless this browser was marked as trusted, for 30 days (taken fromMFA_TRUST_COOKIE_AGE, not hard-coded), and correct the docstring instages.py. New strings go throughmakemessagesas usual.Done when
tests/test_mfa.pygives a person only a WebAuthn authenticator and finds that the Account page does not mention an authenticator app, and that the password line mentions a trusted browser; the same page for a TOTP-only account still names the app.