"Supabase MFA TOTP in Flutter: 2FA Setup Guide"

Supabase MFA TOTP in Flutter: mfa.enroll() QR flow, challengeAndVerify(), AAL1/AAL2 checks, unenroll, and RLS enforcement. Complete 2FA guide.

Passwords leak. Phishing works. If your Flutter app handles anything worth protecting — payments, health data, admin panels — a password alone isn't enough. Supabase MFA TOTP in Flutter gives you proper two-factor auth with any authenticator app (Google Authenticator, 1Password, Authy), using the MFA APIs built into supabase_flutter . The flow is four calls: mfa.enroll() to create the factor and get a QR code, display it, mfa.challengeAndVerify() to confirm the first code, and getAuthenticatorAssuranceLevel() to gate sensitive actions on AAL2. This tutorial implements all of it with runnable code. *Last updated: October 3, 2026* What you'll learn How Supabase MFA works: AAL1 vs AAL2 explained Enabling TOTP factors in the dashboard and adding qr_flutter Enrolling a TOTP factor with mfa.enroll() and showing the QR code Verifying codes with challengeAndVerify() Checking assurance levels with getAuthenticatorAssuranceLevel() Unenrolling factors (and the insufficient_aal trap) Enforcing AAL2 in RLS policies for sensitive tables Why listFactors() sometimes returns no TOTP factor How Supabase MFA Works: AAL1 vs AAL2 Supabase Auth tracks an Authenticator Assurance Level (AAL) per session: AAL1 — the user signed in with a single factor (password, magic link, OAuth). This is the default after login. AAL2 — the user completed a second factor (TOTP code). This is what "MFA verified" means. Your app doesn't have to require MFA at login. The common pattern is step-up auth : let users sign in normally (AAL1), then demand AAL2 only for sensitive actions — changing email, viewing billing, admin screens. getAuthenticatorAssuranceLevel() tells you which level the current session holds, and RLS can enforce it per table. TOTP factors are per-user: one user can enroll multiple…

Explore