Files
sencho/docs/operations/two-factor-admin.mdx
T
Anso 4722028904 feat(mfa): UX hardening — auto-submit, paste tolerance, low-codes warning, dev-mode diagnostics (#620)
* feat(mfa): auto-submit 6-digit TOTPs and normalize pasted backup codes

Match the UX every major MFA prompt has (GitHub, GitLab, 1Password): the
challenge screen and every code-entry dialog now submit automatically once
the sixth TOTP digit lands, and the backup-code input accepts pastes with
smart-dashes, trailing whitespace, or mixed case without silently
truncating the value. Also caps the backup-code input at the correct
11 characters (10 plus a single separator) instead of 12.

Shared normalization helpers live in frontend/src/lib/mfa.ts so the
challenge and the three account-settings dialogs stay in lockstep.

* feat(mfa): warn users when backup codes run low

The Account & Security card silently showed a dim count of backup codes
remaining, which meant users could drift toward zero without noticing
until their phone was already lost. The card now surfaces a warning tone
with an alert icon when 1 or 2 codes remain, and swaps to a dedicated
destructive warning card with a "Regenerate now" action when the user
has used every code.

* feat(mfa): gate diagnostic logs behind developer mode

Reuses the existing isDebugEnabled() gate so operators investigating a
2FA support ticket can flip Developer Mode on to get per-branch
diagnostics (login path taken, replay check outcome, failure counter
after a verify, replay-table purge counts), and flip it back off when
they are done. Standard lifecycle logs stay on by default: enrolment
completed, 2FA disabled, backup codes regenerated, admin reset, SSO
bypass toggled, lockout engaged. Nothing that could reveal a TOTP code,
base32 secret, backup-code cleartext, or partial-auth JWT is ever
logged.

* test(mfa): cover drift, invalid formats, lockout recovery, and paste normalization

Backend: a TOTP generated for a window that has already slid out is
rejected, malformed backup codes (too short, non-alphanumeric, 11-char
alphanumeric that matches no hash) all increment failed_attempts, a
successful verify clears a below-threshold failure streak, a successful
verify after locked_until has passed clears the lockout, a second
enroll/start overwrites the prior pending secret, and the backup-code
normalizer treats en-dash/em-dash/figure-dash with stray whitespace the
same as the canonical form.

E2E: low-backup-codes warning renders in the warning tone and the
exhausted-codes state flips to the dedicated warning card, a 6-digit
TOTP auto-submits without a button click, and a backup code pasted
without the separator still signs in.

* docs(mfa): auto-submit, paste guidance, and expanded troubleshooting

Document that the challenge screen submits automatically on the sixth
digit, that backup codes accept the separator and any case, and that
the Account & Security card nudges at low code counts. Expands the
troubleshooting section with entries for lost or exhausted backup codes
and adds a short note to the admin guide about surfacing auth
diagnostics via Developer Mode.
2026-04-15 19:51:44 -04:00

63 lines
3.2 KiB
Plaintext

---
title: Managing Two-Factor Authentication
description: Reset a user's 2FA, configure per-user SSO enforcement, and recover from lockouts.
---
This guide is for administrators. For general 2FA usage, see [Two-Factor Authentication](/features/two-factor-authentication).
## Reset a user's 2FA
A user who has lost their authenticator app and all backup codes cannot sign in on their own. Any administrator can reset the affected account from the Settings UI.
1. Open **Settings → Users**
2. Find the user in the list. Users with 2FA enabled show a shield icon in the action column
3. Click the shield icon and confirm the reset
<Frame>
<img src="/images/two-factor-auth/admin-reset.png" alt="Administrator resetting a user's 2FA from the Users settings" />
</Frame>
After the reset:
- The user can sign in with their password only, no second factor is required
- Their existing sessions are invalidated, so any stale browser tabs have to sign in again
- The action is recorded in the audit log with the administrator's username
Instruct the user to enrol again from **Settings → Account & Security** as soon as they are back in. The account is unprotected until they do.
## Emergency recovery from the command line
If every administrator has lost access to 2FA and no one can sign in through the UI, reset the admin account directly from the host running Sencho.
From a shell on that host:
```bash
docker compose exec sencho node dist/cli/resetMfa.js <username>
```
Replace `<username>` with the admin's account name. On success the command prints a confirmation line and exits 0. Sign in with the password, then re-enrol immediately.
The command respects the container's `DATA_DIR`, so it always acts on the same SQLite database the application uses. It writes an audit log entry attributed to `cli` so the action is auditable after the fact.
<Note>
Turning on **Developer Mode** in **Settings → Developer** surfaces additional authentication diagnostics in the backend logs. These are helpful when investigating a 2FA support ticket, and can be turned off again once the issue is resolved.
</Note>
## Per-user SSO enforcement
When SSO (LDAP or OIDC) is configured, users with 2FA enabled sign in through SSO without a second factor by default. SSO is already an authenticated flow, and requiring a TOTP on top is extra friction that most teams do not need.
Each user can opt into stricter behaviour by flipping **Require 2FA even when signing in via SSO** on their own Account & Security screen. There is no admin-wide override, every user decides for themselves.
If your organisation needs to force 2FA for every SSO sign-in for every user, raise this with the Sencho team, it is not exposed as a global policy today.
## What a reset changes in the database
For completeness, a reset does the following to the target user:
- Clears the stored TOTP secret and all remaining backup codes
- Rotates the user's session version, which invalidates any outstanding session cookies
- Leaves the account otherwise unchanged, the username, password hash, role, and audit history are preserved
Nothing about the user's SSO bindings changes. If the user was signing in with SSO plus 2FA, they simply resume SSO-only sign-in after the reset.