Multi-factor authentication asks for proof from more than one of three categories:
- Something you know — password, PIN.
- Something you have — phone (for SMS), authenticator app, hardware security key.
- Something you are — biometric (fingerprint, face).
A password alone proves only "you know the password" — phishable, leakable, reusable across services. A password plus a TOTP code from your phone adds "you have the device the TOTP secret lives on" — phishable still, but you'd need to compromise both.
WebAuthn / passkeys raise the bar further by being phishing-resistant: the credential binds to the domain it was registered against. A passkey for cymmetri.com won't sign for cymmetri-spoofed.com even if the user tries. The "something you have" category gets phishing resistance without needing extra hardware.
IntelliAuth supports five MFA factor types:
- TOTP (Time-based One-Time Password) — authenticator apps like Google Authenticator, Authy, 1Password. The user scans a QR code at enrolment; the app generates a 6-digit code that rotates every 30 seconds. Cheap, ubiquitous, phishable.
- WebAuthn / passkeys — hardware security keys (YubiKey, Titan) or platform authenticators (Touch ID, Windows Hello, Android biometric). Phishing-resistant. The strongest factor.
- SMS — code sent via SMS. Familiar to users, low-friction, but phishable + SIM-swappable. Use as a fallback, not the primary.
- Email OTP — code sent via email. Treat as roughly equivalent to SMS in security, sometimes better (depends on the user's email security).
- Recovery codes — single-use codes generated at MFA setup. The user prints them or saves them somewhere safe. Only used when they've lost their primary MFA factor.
Enrolment vs. challenge
Section titled “Enrolment vs. challenge”Two distinct moments:
- Enrolment is when the user sets up a factor — scanning the TOTP QR code, registering the security key, etc. Happens once per factor.
- Challenge is when the platform asks the user to prove a factor — typing the TOTP code at sign-in, tapping the security key. Happens at every flow that requires MFA.
The SDK has separate methods for each. useIntelliAuth().startMfaEnrolment(factor) starts an enrolment; the redirect-based sign-in flow handles challenges transparently (the user sees an MFA challenge page if needed; the SDK returns control once they complete it).
When MFA fires
Section titled “When MFA fires”Three driving factors decide whether a user sees an MFA challenge on a given sign-in:
- Tenant policy. Authentication policy might require MFA always, optional, or never.
- AAL requirements. The action requested needs AAL2 or AAL3; the session has only AAL1; challenge to step up.
- Risk signals. The platform's risk engine flags this sign-in attempt as unusual; ask for MFA even on an MFA-optional policy.
From your code's perspective, MFA challenges are mostly transparent — they happen inside the redirect-based sign-in flow. The SDK returns control once the user completes the challenge (or aborts).
The case you do handle is step-up: the user is already signed in, but tries to do something high-value, and the API returns mfa_required. Your code calls the SDK's step-up method to trigger a challenge without a full re-sign-in. See Step-up authentication.
What "MFA enrolled" looks like
Section titled “What "MFA enrolled" looks like”You can read a user's MFA state from the SDK:
const { listMfaEnrollments } = useIntelliAuth()const enrolments = await listMfaEnrollments()// → [{ id, factor: 'totp', name: 'iPhone Authenticator', enrolledAt }, ...]Useful for showing a settings UI ("you have these factors enrolled, want to add another?"). The platform manages the enrolments; your code just reads + reflects them.
What MFA can't do
Section titled “What MFA can't do”A correction worth stating: MFA isn't a silver bullet. It defeats password-only attacks and most phishing; it doesn't defeat:
- Session token theft — if an attacker steals the session cookie or refresh token after sign-in, they're past the MFA check. Defend with HttpOnly cookies, short token TTL, denylist on suspicious sessions.
- Malware on the user's device — if their machine is compromised, any factor they enter is at risk.
- Social engineering — convincing the user to approve a push notification they didn't initiate. Push-based MFA is the most vulnerable to this; phishing-resistant factors (passkeys) defeat it.
MFA is one layer; it's necessary but not sufficient. Treat it as part of defence in depth.