Learn TOTP-based Two-Factor Authentication (2FA) from the basics to production-grade: pre-requisite skills & environment setup, history & why you need it, core TOTP concepts & main architecture, login & session authentication foundations, generating secrets & otpauth URIs, QR codes & provisioning on the frontend, first-code enrollment verification, storing secrets securely, login flows with a 2FA challenge, backup & recovery codes, rate limiting & replay protection, disabling, reset & secret rotation, database schema & data management, hardening transport with HTTPS cookies & CSP, OWASP & security best practices, session tokens & trusted devices, testing with RFC test vectors & E2E on real devices, going beyond TOTP to WebAuthn & passkeys, enterprise enforcement & compliance, UX accessibility & copy-paste, production deployment secrets & observability, the 2026 ecosystem of providers & authenticator apps, alternative ecosystems & final reflections, across 23 episodes.
Before building a TOTP-based 2FA feature, you need to master JavaScript and TypeScript, basic password session JWT authentication, and SQL. In this episode you will also set up Node.js 24 LTS, install otplib, qrcode, and express-rate-limit, and install Google Authenticator to test scanning and codes.

This episode traces the evolution of authentication from passwords to WebAuthn passkeys, the RFC 4226 and RFC 6238 standards that gave birth to HOTP and TOTP, why passwords are weak against credential stuffing, and why the possession factor and enterprise compliance make 2FA a necessity.

This episode dissects the anatomy of a TOTP code: the Base32 shared secret, the time counter of the epoch divided by 30 seconds, HMAC-SHA1, and truncation into 6 digits. You will also learn the end-to-end architecture from generating the secret, the QR code, the first verification, up to a two-step login, including the importance of clock synchronization.

Before adding the 2FA layer, this episode builds the authentication foundation: password registration and login with bcrypt, HttpOnly session cookies and JWT, the user model structure with a TOTP secret column, and the auth endpoint map that will be injected with the MFA challenge in episode 8.

This episode covers generating a random TOTP secret that is unique per user with otplib, assembling the otpauth provisioning URI that Google Authenticator recognizes, encoding the issuer and account, and why RFC 3548 Base32 is the shared language of all authenticator apps.

This episode turns the provisioning URI into a QR code that Google Authenticator can scan, renders it on the server with qrcode and shows it only once during enrollment, plus designs the Enable 2FA page with a manual secret option for users without a camera.

This episode closes the enrollment flow: the user enters 6 digits after scanning the QR, the server verifies them with authenticator check and a window tolerance, and only then enables totpEnabled. You will also see when the recovery codes are first displayed.

This episode explains why a TOTP secret must not be stored in plaintext, how to encrypt it with AES-256-GCM using a key from the MFA_ENCRYPTION_KEY environment variable, plus the practices of one secret per user and logging that never includes a secret or a code.

This episode turns login into two steps: a password verification that only marks pendingMfa, then a TOTP code verification that finally grants a full session. You will also learn the separation of the /login and /login/mfa endpoints and how to prevent bypassing protected routes before MFA completes.

This episode covers recovery codes as the way out when the authenticator is lost: creating 10 single-use codes, displaying them once, storing them as hashes like passwords, marking used codes, and replacing the whole batch on regeneration.
