Repository navigation
Server, Admin: Add two-factor authentication with TOTP - #342
Merged
Merged
Conversation
lehni
added this pull request to stack #341
October 16, 2026 23:25
lehni
force-pushed
the
feature/totp
branch
2 times, most recently
from
October 17, 2026 01:25
6e27314 to
f77b6fb
Compare
- Add app.auth.totp and app.auth.credentials.secret, checked on setup, through the optional peer otpauth - Store the TOTP secret encrypted and bound to its user, and the backup codes hashed, as credentials - Answer codeRequired to password logins of users with TOTP, with a new session id, completed through 'post login-code'; passkey logins skip it - Add the user's own TOTP actions to UsersController, only routed with TOTP; lock accounts for 15 minutes after ten wrong codes in a row, and verify codes with the credentials locked - Ask for the code after the password in the admin's login dialog, and set up and turn off TOTP in its Security dialog with login.totp, through the peer lean-qr
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.
Builds on #340. Users can protect password logins with a second factor: time-based one-time codes (TOTP) from an authenticator app, plus backup codes.
Server:
app.auth.totp: { issuer }, withapp.auth.credentials.secretrequired to encrypt the secrets. The secret is never derived fromapp.keys, so rotating those doesn't make the secrets unreadable.UserMixin.login()keeps a pending login in the session (5 minutes, with a new session id) and resolves tonull. After 10 wrong codes in a row, logins and code checks of the account are locked for 15 minutes; codes are checked with the credential rows locked, so parallel requests can't reuse a code. The encrypted secret is bound to its user.post loginthen answers{ success: false, codeRequired: true }, andpost login-codewith a TOTP or backup code completes the login. Codes can't be used twice. Passkey logins skip TOTP.get totp,post totp(otpauth URI),post totp-confirm(returns the backup codes once),delete totp(needs a code). They're only routed withapp.auth.totp.otpauthis an optional peer, imported once inUsersController.setup().Admin:
codeRequired.login: { totp: true }adds a Two-Factor Authentication section to the Security dialog, built from schema components: set up with a QR code (lean-qr, a required peer) or the key and a first code, then the backup codes are shown once; turning it off asks for a code.minDuration: dialogs submitted right after they opened stay visible that long. The code dialog of the login stays for a second, so users see their password manager fill in and submit the code.Behaviour change:
UserMixin.login()resolves tonullandpost loginanswerscodeRequiredfor users with TOTP. Users without TOTP aren't affected.