Authentication
A second factor protects the path to your seal
A professional seal carries legal weight. We require MFA enrollment before any user can seal, and we re-verify a fresh TOTP (or backup code) at sealing time. The first seal in a session prompts the second factor; subsequent seals within a 10-minute sudo window pass through. This pattern aligns with 21 CFR Part 11 §11.200(a)(1)(i): the first signing in a continuous period uses all electronic signature components; subsequent signings use at least one. TOTP secrets are AES-256-GCM encrypted at rest; backup codes are bcrypt-hashed.
Executive summary
We use TOTP-based MFA (RFC 6238) and require it before any user can seal. Sealing additionally re-verifies the second factor: the first seal in a session prompts a TOTP code (or one-time backup code); subsequent seals within a 10-minute sudo window pass through. The TOTP secret is encrypted at rest with field-level AES-256-GCM, and the backup recovery codes are stored as Bcrypt hashes — even a database read alone cannot bypass the gate.
FIDO2 / WebAuthn passkeys are on the roadmap. Passkeys are phishing-resistant, device-bound, and have no shared secret — strictly stronger than TOTP. SMS is explicitly not on the path; NIST has been deprecating it as a second factor since 2016 for cause.
Our commitments
Five rules for the second factor
MFA enrollment is required to seal, and a step-up check runs at sealing time on a 10-minute sudo window.
MFA step-up at sealing time (10-minute sudo window)
MFA enrollment is required before any user can issue a seal. At sealing time, the first seal in a session prompts a fresh TOTP (or one-time backup code); subsequent seals within a 10-minute window pass through. This mirrors 21 CFR Part 11 §11.200(a)(1)(i): the first signing in a continuous period uses all signature components; subsequent signings use at least one.
The TOTP secret is encrypted at rest
The shared secret between user and authenticator is field-level AES-256-GCM encrypted with redact: true. A database read does not yield usable secrets.
Backup codes are Bcrypt-hashed
Recovery codes are stored as Bcrypt password hashes — slow to brute-force, single-use, marked used at the moment of redemption in a single transaction.
Verification is timing-safe
TOTP and backup-code verification paths take the same observable time. An attacker cannot tell whether they failed because the code was wrong or because the code was a different type.
No SMS, ever
SS7 attacks, SIM swapping, carrier-side inspection — SMS as a second factor has been deprecated by NIST since 2016. We do not offer it as an option.
Implementation — TOTP
How TOTP is hardened
Implementation — backup codes
How recovery codes are hardened
The full picture
What is built, what is being built, and what we chose not to build
Live today
TOTP-based MFA via NimbleTOTP
LiveRFC 6238 with 6-digit codes, 30-second steps, ±1-step drift tolerance. Compatible with every mainstream authenticator app.
Step-up MFA at sealing (10-minute sudo window)
LiveMFA enrollment is required to seal. The first seal in a session prompts a fresh TOTP (or one-time backup code); subsequent seals within a 10-minute window pass through without re-prompting. The same gate applies to single-doc seals and batch seals — one verification authorizes the batch. Aligns with 21 CFR Part 11 §11.200(a)(1)(i).
Field-level encrypted TOTP secret
LiveAES-256-GCM at rest with redact: true; the shared secret never reaches logs, telemetry, or Inspect output.
Bcrypt-hashed backup codes
LiveSlow-hash storage rate-limits offline brute-force. Single-use marking is atomic at redemption time.
Timing-safe verification
LiveTOTP and backup paths take the same observable time. Failures look identical regardless of code type.
QR-code onboarding with manual fallback
LiveServer-rendered SVG QR; manual base32 entry for environments without a camera.
Building now
WebAuthn / FIDO2 passkey enrollment
Building nowDevice-bound public-key authentication. Phishing-resistant — the credential is bound to the relying party origin and cannot be replayed elsewhere. No shared secret to leak.
Target: enrollment in /settings/security this quarter. Sealing-gate integration follows.
Step-up authentication for sensitive non-sealing operations
Building nowRe-prompt MFA on credential changes, payment-method updates, member role escalation, and SSO config changes. Today's gate is sealing-only; this expands the surface.
Hardware security key enforcement (Enterprise policy)
Building nowOrg admins can require a FIDO2 hardware key for sealing, optionally limiting accepted vendors (YubiKey, Feitian, etc.). Locks out TOTP and platform passkeys for the strictest compliance regimes.
Roadmap
Passkey-only mode
RoadmapAn org-level setting that disables TOTP entirely for the org's users, leaving passkeys as the only second factor. For customers running NIST AAL3 environments.
Device attestation at enrollment
RoadmapVerify the FIDO2 authenticator's manufacturer attestation at enrollment time so org admins can constrain which physical devices are acceptable.
Risk-based step-up
RoadmapA risk-scored login (new geo, new device, anomalous time-of-day) triggers a step-up challenge regardless of the operation. Today, sealing is the only step-up trigger.
Considered & rejected
SMS-based MFA
Considered & rejectedSS7 attacks, SIM swapping, carrier-side inspection. SMS has been deprecated by NIST as a second factor since SP 800-63B-2016.
Why we rejected it: every "we'll just SMS the code" is a way to ship a known-broken second factor for the convenience of users who do not own a smartphone with an authenticator app. The right answer is: TOTP works on every phone. Passkeys work on every modern device. SMS is a security regression we will not subsidize.
Email-based MFA
Considered & rejectedIf the email is compromised, MFA is bypassed. Email is a recovery channel, not a second factor.
Why we rejected it: an attacker who has the password very often has the email. Email-as-second-factor collapses to single-factor in those cases. We use email for password recovery — explicitly named as such — and never as MFA.
Persistent "remember this device for 30 days" MFA bypass
Considered & rejectedThe most common path to professional account takeover. We do not offer it, even though competitors do.
Why we rejected it: every "remember me" is a prefilled answer to "did you actually verify the human?" For sealing — a legally significant act — the friction of MFA every time is the feature. The cost is one 6-digit code; the benefit is that a stolen session cannot produce a forged seal.
Push notifications as a second factor
Considered & rejectedPush fatigue is a documented attack vector — users approve prompts they did not initiate.
Why we rejected it: the 2022 Uber breach is the canonical example. Push approvals are a usability win when paired with number-matching (where the user types a code from the prompt back into the app), and we may revisit number-matched push for non-sealing step-up. As a primary factor, push without number-matching is a regression we will not ship.
Storing the TOTP secret in plaintext for "operational ease"
Considered & rejectedPlaintext shared secrets in a database is the textbook example of a horizon-of-failure leak.
Why we rejected it: every "we keep it plaintext for backup recovery" is a way for one breach to compromise every user's second factor. Encrypting it is one extra symmetric operation per verification. We pay it.
Recovery via security questions
Considered & rejectedSecurity questions are public information and have been since LinkedIn data leaked in 2012.
Why we rejected it: mother's maiden name, first pet, high school — all of these are findable. Backup codes are unguessable cryptographic random. They are the right primitive for "I lost my authenticator." We do not invent a worse one.
Compliance mappings
Controls this surface satisfies
Logical Access — Authentication
Session MFA; encrypted secret; hashed backup codes
Logical Access — Network Segmentation
MFA verifies the human regardless of network origin
Secure log-on procedures
Multi-factor with hardened secret storage and timing-safe verification
Password management system
Backup codes stored as Bcrypt hashes; never displayed twice
Authentication Assurance Level 2
TOTP today (multi-factor cryptographic); AAL3 with passkeys, in progress
Person or Entity Authentication
Verifies the user before access to protected health information surfaces
Electronic signature components
Two distinct identification components required for signing
Multi-factor authentication
Standard MFA for all administrative access
For compliance teams
Questions you do not need to call to ask
Which authenticator apps are supported?
What happens if a user loses their authenticator and their backup codes?
When do passkeys ship?
Can MFA be required at the org level?
How are TOTP codes verified server-side?
What if our org uses SSO — do users still need MFA on top?
Are MFA failures rate-limited?
The friction is the feature
Read the device & session page for the broader session-integrity story, or talk to our security team about org-specific MFA policies.