Multi-factor authentication
Multi-factor authentication (MFA) adds a second step after the password (or social / magic-link) sign-in. Huudis supports two factors, and a user can enrol either or both:
- Authenticator app (TOTP) — a 6-digit code from an app like Google Authenticator, 1Password, or Authy.
- Email code — a 6-digit code Huudis emails to the user's verified account email.
MFA is opt-in per user. Users manage their factors in the portal on the
Authentication page (/dashboard/authentication) — open
Multi-factor authentication → Manage factors to enrol, list, or remove
them. (The old standalone "Security & MFA" page has been folded into the
Authentication hub.)
Enrolling
Authenticator app — Huudis shows a QR code (and a secret to type manually); the user scans it and confirms with the first 6-digit code. On their first factor, Huudis also issues one-time backup codes — store them somewhere safe.
Email code — Huudis emails a code to the account address; the user enters it to confirm. (Because the account email is already verified, there's nothing extra to set up.)
Signing in with MFA
After the first factor, if the user has any verified factor Huudis returns an
mfa_required challenge instead of a session. The challenge tells the
sign-in screen which factors are available:
- If an email factor is present, Huudis emails a code immediately and the screen prompts for it (with a Resend option, throttled to once every 30 seconds; codes are capped at 5 attempts).
- If a TOTP factor is present, the screen prompts for the authenticator code.
- If the user has both, either code is accepted.
- A backup code is always accepted as a fallback.
On success Huudis issues the session and marks it MFA-verified. The challenge is short-lived and single-use.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/auth/mfa/enroll |
{ method: 'totp' | 'email', label? } |
POST |
/api/v1/auth/mfa/verify-enrollment |
{ deviceId, code } |
POST |
/api/v1/auth/mfa/resend-enrollment-code |
resend the email enrollment code |
GET |
/api/v1/auth/mfa/challenge?token= |
which methods this challenge offers (non-consuming) |
POST |
/api/v1/auth/mfa/resend-code |
resend the login email code |
POST |
/api/v1/auth/mfa/verify-login |
{ token, code } — TOTP, email code, or backup code |
GET |
/api/v1/auth/mfa/devices |
list enrolled factors |
DELETE |
/api/v1/auth/mfa/devices/:id |
remove a factor |