Guides / Prompting and shipping

How to Add Two-Factor Authentication to Your App

Add 2FA to your app step by step: authenticator codes vs passkeys vs SMS, enrolment, recovery codes, server-side checks and the mistakes to avoid.

Mythex Team · 2026-09-29 · 7 min read

To add two-factor authentication (2FA) to your app, let users link an authenticator app by scanning a QR code, ask for the six-digit code it shows after the password, and only create a full session on the server once that code checks out. Give every user single-use recovery codes when they turn it on, limit how many codes someone can guess, and require the password plus a current code before 2FA can be switched off. If you use a hosted auth provider, turn on its built-in multi-factor option instead of building your own.

This guide walks through the choices, the exact flow, prompts you can give an AI builder, and the mistakes that make 2FA look present but do nothing. If the concept is new, start with what two-factor authentication is.

Before you start: you need a working login

2FA sits on top of an existing sign-in. You need one of these first:

  • Your own login, with users and hashed passwords stored in your app's database.
  • A hosted auth provider that manages users for you.

If you don't have either yet, begin with how to add login to your app. The rest of this guide assumes a password step already works.

Pick your second factor

MethodUser effortSecurityCost to runGood default?
Authenticator app (TOTP)Scan a QR code once, type a code at loginGood; phishable if a fake site asks for the codeFreeYes, for most apps
Passkey or security keyTap or use a fingerprintStrongest; resists phishingFreeYes, if your users are comfortable with it
Email codeCheck inbox at loginOnly as strong as the email accountEmail sending costsAs a fallback only
SMS codeWait for a textWeakest; SIM swapping and phishingPer-message feesOnly if users can't use an app

TOTP stands for time-based one-time password, the standard (RFC 6238) that authenticator apps use. Your server and the user's phone share a secret; each generates the same short code from that secret and the current time, usually changing every 30 seconds. No network connection or SMS provider is needed.

Passkeys replace or supplement passwords with a cryptographic key stored on the user's device. They are stronger but more work to build yourself, so many apps start with TOTP and add passkeys later, or get them from an auth provider.

Build it or turn it on?

ApproachProsCons
Hosted auth provider's MFALess code; the provider maintains the security detailsMonthly cost at scale; you depend on the provider's options
Your own TOTP with a libraryFull control; no per-user feeYou own the edge cases: lockouts, recovery, secret storage

Check your provider's current documentation for which factors it supports and on which plans. Either way, never write the code-generation maths yourself; use a widely used library.

Decide the policy first

Answer these before you prompt, because they change the design:

  1. Who must use it? Optional for everyone, required for admins and staff, or required for all. Requiring it for anyone with admin power is common. See role-based access control.
  2. How often do users re-enter a code? Every login, or once per device for 30 days ("remember this device").
  3. Which actions need a fresh check? Changing the email, payout details, or turning 2FA off are good candidates. This is called step-up authentication.
  4. What is the lost-phone process? Recovery codes, plus a manual fallback you are willing to run.

Step by step: TOTP 2FA on your own login

1. Store the right fields

Each user needs: whether 2FA is enabled, the TOTP secret (encrypted at rest, not plain text), the time it was enabled, and a list of recovery codes stored hashed, like passwords. Add a place to count failed attempts.

2. Enrolment

  1. The user opens Settings and clicks Turn on two-factor authentication.
  2. The server generates a new secret and returns it as a QR code, plus the text version for people who can't scan.
  3. The user scans it in an authenticator app and types the current code.
  4. The server checks the code. Only if it's correct does it save the secret and mark 2FA as enabled.
  5. The app shows 8–10 recovery codes once and asks the user to save them.

Step 4 matters: switching 2FA on before confirming a code locks out anyone whose scan failed.

3. Login with a second step

  1. The user submits email and password. The server checks them.
  2. If 2FA is enabled, the server does not create a full session. It creates a short-lived "second factor pending" state instead.
  3. The app shows the code screen. The server checks the code, allowing a small window for clock drift.
  4. Only now does the server issue the real session.

Every protected route and API endpoint must reject the pending state. A 2FA screen that only hides pages in the browser can be skipped by calling the API directly.

4. Limits and alerts

A six-digit code has a million combinations, which is guessable without limits. Cap attempts, lock the second step for a period after repeated failures, and email the user when that happens. See rate limiting and sending emails from your app.

5. Recovery and turning it off

  • A recovery code works once, then is deleted.
  • Disabling 2FA requires the password and a current code or recovery code.
  • Regenerating recovery codes invalidates the old set.
  • Email the user whenever 2FA is turned on or off.

Prompts to give your AI builder

Start with the core flow:

Add optional two-factor authentication using authenticator apps (TOTP) to our existing email and password login. Use a well-known TOTP library, don't write the algorithm yourself. In Settings, show a QR code and the text secret, and only enable 2FA after the user enters a valid code. Store the secret encrypted and never show it again after setup. Show 10 single-use recovery codes once and store them hashed.

Then the enforcement, which is where generated code most often falls short:

Enforce 2FA on the server. After a correct password, users with 2FA enabled get a short-lived pending state, not a full session. Every protected page and API route must reject the pending state. Limit code attempts to 5, then lock the second step for 15 minutes and email the user.

Then policy:

Require 2FA for admin accounts: an admin without 2FA is sent to setup and can't reach the dashboard until it's done. Require the password and a current code to turn 2FA off or change the account email. Email the user when 2FA is enabled or disabled.

Finally, ask the agent to explain what it built:

List every route that checks for a completed second factor, where the TOTP secret and recovery codes are stored, and how they're protected.

Common mistakes

  • Session issued after the password. The most serious bug. If the full session exists before the code is checked, 2FA is decoration. Test by calling a protected API after the password step only.
  • No attempt limit. Unlimited guesses make the code brute-forceable.
  • Plain-text secrets or recovery codes. A database leak then hands over everyone's second factor.
  • Enabling before verifying. Users who mis-scanned are locked out at next login.
  • No recovery path. Every lost phone becomes a support ticket or a lost customer.
  • Easy switch-off. If a stolen session can disable 2FA without a code, the protection is gone.
  • Codes in logs. Make sure codes and secrets never appear in server logs or error messages.
  • Checking only on the login page. Password reset, "magic link" sign-in and any social login must respect 2FA too, or they become a way around it.

Testing checklist

  • Enrolment only completes after a valid code
  • Login with a correct password but no code gives no access to any protected page or API
  • A wrong code is rejected; repeated wrong codes trigger the lockout and an email
  • A code from a few minutes ago is rejected
  • Each recovery code works exactly once
  • Turning 2FA off needs the password and a current code
  • Password reset does not bypass 2FA
  • Admins without 2FA can't reach admin pages (if required)
  • Secrets and recovery codes are encrypted or hashed in the database
  • No codes or secrets appear in logs

Run the full security checklist for AI-built apps before launch too.

Adding 2FA in Mythex

Mythex doesn't include a built-in login system for your app's end users, so 2FA is part of whichever auth approach you choose: your own email-and-password login using the project's database, or a hosted provider with multi-factor support. You describe what you want in chat using prompts like the ones above, and any provider keys go in project secrets (through /secrets, project settings or the secrets card the agent shows) rather than in the message box. The docs recipe Add login to your app has a starter prompt, and Security for apps you build covers the habits around keys and permissions. After the agent finishes, test every item on the checklist in Preview before you publish.

Questions

What is the easiest way to add two-factor authentication to an app?

If you use a hosted auth provider, turn on its built-in multi-factor option; that is usually the least code. If you run your own login, add authenticator-app codes (TOTP) with a well-known library, plus recovery codes and a server-side check.

Should I use SMS codes for 2FA?

SMS is better than no second factor, but it is the weakest common option because texts can be redirected through SIM swapping and codes can be phished. Offer an authenticator app as the default, and passkeys if your users are ready for them.

Do I need a database to add 2FA?

If you run your own login, yes. Each user's 2FA secret, whether 2FA is on, and their hashed recovery codes have to be stored somewhere your server can check. A hosted auth provider stores this for you.

What happens if a user loses their phone?

They sign in with one of the single-use recovery codes you showed when they turned 2FA on, then set 2FA up again on a new device. Without recovery codes, you need a manual identity check, so decide that process before launch.

Keep reading

  • How to Add a Blog to Your Website: Options, SEO and Setup — How to add a blog to your website: Markdown files vs a built-in editor vs a CMS, subfolder vs subdomain, SEO basics, and prompts to build it with AI.
  • How to Add a Contact Form to Your Website (That Actually Reaches You) — How to add a contact form that works: save messages, get email alerts, stop spam, and avoid the mistakes that silently lose enquiries. Prompts included.
  • How to Add a Database to Your App (Without Losing Data Later) — How to add a database to an app you built: when you need one, Postgres vs hosted options, designing tables, prompts to use, and mistakes that lose data.
  • How to Add AI Features to Your App — Add summaries, chat, data extraction and classification to your app with an LLM API — keeping keys safe, costs under control and output trustworthy.
  • How to Add Analytics to Your App: GA4, Privacy-First Tools and Product Analytics — How to add analytics to your website or app: Google Analytics 4 vs privacy-first vs product analytics, what to track, cookie consent, and prompts to use.
  • How to Add Cookie Consent to Your Website — Add a cookie banner that actually blocks scripts until people agree: what needs consent, CMP vs custom, Google consent mode and a checklist. Not legal advice.

Start building free · Templates · Docs