Two-factor authentication
TOTP enrolment, recovery codes, and the sign-in challenge.
Turn it on for every account with access
Anyone with admin access to the portal has root on the server. It is under account settings and takes one scan.
Enrolling
Start enrolment — POST /auth/two-factor. It re-authenticates with your
password first; an open session is not enough to add a second factor to an
account.
Scan the QR code with any authenticator app. The platform implements RFC 6238 TOTP, verified against the specification's own published test vectors.
Confirm with a code — POST /auth/two-factor/confirm. Enrolment is not
complete until a code from the app is accepted, so a mis-scanned secret
cannot lock you out.
Disabling two-factor re-authenticates with the password the same way.
Signing in with it on
Sign-in returns a challenge rather than a session. POST /auth/two-factor/verify — the one
public route in this group — takes that challenge and a code, and issues the session.
How the two secrets are stored
| Stored as | Why | |
|---|---|---|
| The TOTP seed | Encrypted under the master key | It has to be recoverable to verify a code. |
| Recovery codes | HMAC digests, single-use | They never need to be readable, only comparable. A digest cannot be turned back into a code by anyone who reads the database. |
A recovery code is consumed when used and cannot be used again.
If you lose both
There is no remote reset. The account's two-factor row has to be removed from the database on the box — which is another reason to have more than one owner.