Multi-Factor Authentication
How BuddyWorkflow implements and enforces two-factor authentication for end users and administrators, protecting access to financial data connected through Plaid and payments processed through Stripe.
Version: 1.0Status: Available in productionMethod: TOTP (authenticator app)Owner: Founder & Security Lead
1. Summary
BuddyWorkflow supports multi-factor authentication (MFA) in production for both end users and administrators. MFA uses time-based one-time passwords (TOTP) generated by a standard authenticator app (Google Authenticator, Authy, 1Password, etc.), implemented on top of Supabase Auth's native MFA. Once a user enrolls a second factor, it is required on top of email + password at every sign-in before their session is granted.
This control directly strengthens protection of the two most sensitive integrations: Plaid (bank-account connectivity) and Stripe (payments & billing). For an account with a verified factor, a stolen password alone can no longer establish a session that reaches connected financial accounts or payment settings.
2. Scope & Enforcement
- End users: any user may enroll a TOTP factor from Settings → Security. Once enrolled, the factor is challenged at every sign-in and the session is only established after it is satisfied — so a verified user reaches Plaid and Stripe surfaces only from a second-factor-satisfied session.
- Administrators: MFA is mandatory for all personnel with access to production systems — Supabase, hosting/CDN, the Stripe Dashboard, the Plaid Dashboard, GitHub, and Google Workspace. No admin console is reachable with a password alone.
- Sensitive integrations: bank connections via Plaid and payout/billing configuration in Stripe are reached only after a full sign-in, so a verified user's access to them inherits the second-factor requirement enforced at login.
3. Assurance Levels (AAL)
Supabase Auth expresses MFA state as an Authenticator Assurance Level on each session. When an account has a verified factor, BuddyWorkflow steps the session up to aal2 at sign-in before the app is usable.
LevelMeaningWhen it applies
aal1Password only (no verified second factor)Accounts that have not enrolled an authenticator
aal2Password + verified TOTP challenge this sessionAccounts with a verified authenticator — required at every sign-in before the app loads
4. Enrollment Flow
- User opens Settings → Security → Two-factor authentication and selects "Add authenticator app."
- The app calls
supabase.auth.mfa.enroll({ factorType: 'totp' }), returning a QR code and secret. The user scans it into their authenticator app. - The user enters the 6-digit code; it is verified with
mfa.challenge() + mfa.verify(). The factor is marked verified only on success. - The session is elevated to
aal2 and enrollment is complete. From then on the factor is required at each sign-in.
5. Sign-in & Challenge Flow
- Step 1 — Password: the user signs in with email + password (session begins at
aal1). - Step 2 — Factor check: the app reads the assurance level via
mfa.getAuthenticatorAssuranceLevel(). If the account has a verified factor and the session is below aal2, the user is routed to a challenge screen. - Step 3 — Verify: the user enters the current TOTP code;
mfa.challenge() + mfa.verify() elevate the session to aal2. - Step 4 — Access: only an elevated session continues into the app; an unmet challenge cannot proceed.
6. Recovery & Account Lockout
- Lost device: a user who loses their authenticator and cannot produce a code must complete an identity-verification step with support before a factor is reset.
- Factor reset: support-assisted resets are performed only after identity verification and are logged.
- Managing factors: adding or removing an authenticator is done from Settings → Security while signed in as the account holder.
7. Protection of Plaid & Stripe
Plaid: bank credentials are never seen by BuddyWorkflow — they are entered only inside Plaid Link. Because a verified user reaches the app only from a second-factor-satisfied session, only a strongly-authenticated user can initiate a bank connection or retrieve transactions via a stored Plaid access token.
Stripe: payment and payout configuration is reached only from a signed-in session, and the Stripe Dashboard itself is MFA protected. Webhooks are verified by signature and processed server-side, independent of the user session.
8. Logging & Monitoring
- MFA enrollment, verification success/failure, and factor removal are captured in Supabase Auth logs.
- Repeated failed challenges can be surfaced for review as a possible account-takeover signal.
- Admin MFA events on Stripe, Plaid, and GitHub are retained in each provider's audit log.
9. Roadmap
- One-time recovery codes issued at enrollment as a self-service backup if a device is lost.
- Optional WebAuthn / passkey factor as a phishing-resistant alternative to TOTP.
- Enforced MFA as an org-level policy for workspaces on the Pro plan.
- Step-up re-authentication prompts on high-risk actions after a session-age threshold.
This control is referenced in the BuddyWorkflow Information Security Policy (§3, Access Control & Authentication). Questions: bryn@buddyworkflow.com.