Skip to content

Multifactor authentication

TinyGuard supports three second factors:

  • WebAuthn passkeys — the phishing-resistant factor. A password followed by a passkey ceremony, or passkey-only accounts. A relying-party client can set force_mfa to require a second factor during interactive authorization.
  • TOTP authenticator (RFC 6238) — six-digit codes, 30-second steps, HMAC-SHA1, with a one-step drift window and replay rejection through the persisted last-accepted step. The seed is sealed with the deployment value cipher before storage and is displayed exactly once, in the standard otpauth:// enrollment URI. Enrollment requires an authenticated session and is confirmed by a live code before the factor becomes active.
  • One-time recovery codes — a ten-code set for lost authenticators. Codes come from the CSPRNG, are stored only as SHA-256 hashes, are consumed atomically one at a time, and rotating the set invalidates every previous code. The full set is displayed exactly once at generation.

An account holding any factor is steered into the same pending second-factor step after the password. The login page offers the passkey ceremony when a credential exists and a code entry when a TOTP or recovery set is enrolled; when both exist the account may complete with either. A recovery code never enrolls a new strong factor by itself.

TOTP and recovery codes are lower assurance than passkeys: an OTP is not phishing-resistant ([NIST SP 800-63B-4]). They complement passkeys; they do not replace them for tenants that require phishing resistance.

Account settings holds the software factors: the authenticator (enroll/confirm/remove) and the recovery set (generate — displays the new codes once — with the remaining count visible at any time). Passkey management sits behind its short-lived modification token as before.

The ID token’s amr claim stays deliberately conservative: mfa only when the account holds a second factor and the token comes from an authorization-code flow (which, by login steering, means the ceremony completed), pwd otherwise. No acr claim is issued. Upstream identity providers’ amr/acr assertions are never copied into local tokens: a federated sign-in stages a tenant-bound local passkey ceremony when the linked account or client requires MFA, and a newly provisioned account without a passkey is refused rather than bypassing the requirement.

  • The platform force_admin_mfa gate and per-client force_mfa remain the enforcement points today; both count any enrolled factor.
  • Tenant factor policy rides the tenant record (mfa_policy): allowed_factors bounds which software factors (totp, recovery) the tenant’s sign-ins may complete with and may be enrolled at all — the passkey factor is always available, since removing it per tenant would brick passkey-only accounts — and admin_floor sets what the tenant’s administrators must complete: none (default), second_factor, or passkey (software completions are refused for administrator accounts; only the phishing-resistant ceremony passes). require_second_factor (off by default) makes every sign-in in the tenant complete a second factor — an account holding none is refused with the MFA-required class until one is enrolled. The tenants screen exposes the whole policy (enforcement, allowed factors, admin floor, in-flow enrollment). federated_inflow_enrollment (off by default) permits a newly provisioned federated account to enroll its first passkey during the sign-in that created it, when the relying-party client demands MFA — otherwise that login is refused (fail-closed). A client may strengthen beyond the floor but never weaken it. Tenant administrators set the policy through the tenant update endpoint; platform administrators may set it for any tenant.
  • Explicit per-provider upstream assurance: a provider record may name trusted upstream amr/acr values; a signature-verified upstream token carrying one lets that ceremony satisfy the force-MFA gate without a local step-up. Unlisted values — or no list at all — change nothing, and upstream amr/acr strings are never copied into local tokens. See Federation.

TOTP follows RFC 6238, and authenticator and recovery handling follows NIST SP 800-63B-4.