โ† Pattern library

Authentication

Two-Factor Authentication

Adds a second verification step (TOTP code, SMS, or push notification) after password to dramatically reduce account takeover risk.

๐ŸŒฟ

When to use this

When the account holds anything valuable โ€” payment info, private data, business resources. Optional for low-stakes apps.

authsecurity2famfatotp
โœจ Built using these library patterns:
2fa

What I assumed

I made these guesses to fill gaps. Let me know if any are wrong.

    Flow diagram

    Step-by-step recipe

    Copy this and paste into Cursor, Claude Code, or v0.

    PATTERN: Two-Factor Authentication (TOTP)
    INPUT: user (post-password-success), totp_code
    OUTPUT: full_session | challenge_failed
    
    STEPS:
      1. User completes password step successfully (composable_with: email-login)
      2. Check IF user has 2FA enabled
      3. IF not enabled โ†’ skip 2FA, create session
      4. Show 6-digit code input screen
      5. User opens authenticator app (Google Authenticator, 1Password, Authy)
      6. User enters current 6-digit code
      7. Server validates code against TOTP algorithm with user's secret
      8. IF valid (within ยฑ30s window) โ†’ mark session as fully authenticated
      9. IF invalid โ†’ show "Code didn't match, try again (3 attempts left)"
      10. After 3 failures โ†’ lock for 15 minutes, require password re-entry
    
    ERROR_HANDLING:
      - User lost device โ†’ offer recovery codes (generated at setup)
      - Clock drift between server and authenticator โ†’ allow ยฑ30s window
      - User enters expired code โ†’ show "That code just expired, try the next one"
      - 3 failed attempts โ†’ temporary lock + email "unusual activity"
    
    EXTENSION_POINTS:
      - Hardware key support (FIDO2/WebAuthn) (composable_with: ["webauthn"])
      - Recovery codes flow (composable_with: ["recovery-codes"])
      - Trust this device for 30 days (composable_with: ["device-trust"])
    

    States โ€” how things change

    StateDescriptionTransitions
    Awaiting 2FA codePassword verified, waiting for second factor
    • Code submittedโ†’Verifying code
    Verifying codeServer validating TOTP
    • Matchโ†’Fully authenticated
    • Mismatchโ†’Awaiting 2FA code
    • Lock triggeredโ†’Account locked
    Fully authenticatedSession active with 2FA verifiedterminal
    Account lockedToo many failures, temporary block
    • Cooldown elapsedโ†’Awaiting 2FA code

    Easy-to-miss situations

    The kinds of edge cases that break demos.

    • What if the user loses their phone with the authenticator app?

      high

      They're locked out forever without recovery method.

      Suggested handling: At 2FA setup, REQUIRE downloading 8-10 recovery codes. Show "Save these somewhere safe โ€” they're your only way back if you lose your phone."

    • What if a phishing site tricks the user into entering their TOTP?

      high

      TOTP codes are valid for ~30s โ€” attacker can use within window.

      Suggested handling: For high-value accounts, prefer hardware keys (FIDO2) which are phishing-resistant by design. Educate users about this attack vector.

    • What if the server's clock drifts from the authenticator's?

      medium

      Valid codes get rejected, frustrating users.

      Suggested handling: Allow ยฑ30 second window in TOTP validation. Use NTP-synced server time. Log clock drift for monitoring.

    • What if the user wants to disable 2FA?

      high

      Disabling without verification is a takeover vector.

      Suggested handling: Require current password + current TOTP code BEFORE disabling. Send confirmation email after disabling. Cool-down before fully removing.

    • What if SMS-based 2FA gets SIM-swapped?

      high

      Attacker takes over phone number, receives codes.

      Suggested handling: Default to TOTP (app-based), not SMS. If you must support SMS for accessibility, mark it as fallback only and warn users.

    Composes well with

    Combine these patterns when you need a richer flow.

    Build a flow starting from this pattern โ†’