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.

Welcome to the Learn 2FA Authentication series! This series will guide you to master TOTP-based Two-Factor Authentication — the standard used by Google Authenticator — from the foundations of the concepts to production-grade deployment. In total there are 23 episodes arranged across six phases.
But before touching any code, there are some basic skills and software you must have. Why are these pre-requisites important? Because a 2FA feature touches three different layers of the system: cryptography for TOTP and secret encryption, a web framework for the login flow, and a database for storing encrypted secrets and recovery codes. If even one layer isn't understood, debugging later will feel like opening a black box.
Episode 0 is your roadmap: we will make sure the basic skills are in place, set up the runtime and packages, then verify the first installation. Once this episode is done, the rest of the series can be followed comfortably.
All implementations in this series use modern JavaScript or TypeScript on Node.js. You must be comfortable with async/await, destructuring, and ES modules. TypeScript is highly recommended because otplib 13.x ships with built-in types — errors like calling a method that doesn't exist will be caught at compile time, not in production.
Check your runtime and package manager versions:
node --version
npm --versionMake sure the output of node --version shows major version 24. This series uses Node.js 24 LTS (Krypton), matching the stable version at the time of writing.
Before adding the second layer, you must understand the first one: password authentication. Master password hashing with bcrypt or argon2 (never store plaintext), then HttpOnly cookie-based sessions or JWT stored on the client. Episodes 3 and 15 will dissect this part in more depth, so just make sure you have built a simple login before.
Encrypted TOTP secrets, the totpEnabled status, and recovery codes are stored in a relational database. You need to understand CREATE TABLE, INSERT, UPDATE, and migrations. This series uses SQLite for the lab and points to PostgreSQL for production — both should feel familiar enough to a web developer.
Install Node.js 24 LTS from nodejs.org or use the LTS version bundled with your distro. Use the built-in npm so package versions stay consistent. Don't forget to note the version, because every example in this series is tested against that runtime.
Pick one framework: Next.js App Router for full-stack examples with React, or Express 5 for a concise API that stays close to Node. Both are fully supported by otplib. The examples in this series are mostly written for Express 5 to keep the focus on the 2FA logic, but every flow can be translated to Next.js route handlers.
Install the core packages used throughout the series:
npm install otplib@13.4.1 qrcode@1.5.4 express-rate-limit@7
npm install --save-dev @types/qrcodeotplib@13.4.1 is the TOTP/HOTP core that follows RFC 4226 and RFC 6238. qrcode@1.5.4 renders QR codes for enrollment, and express-rate-limit@7 protects verification endpoints from brute-force attacks.
For the lab, SQLite is enough — a single file, no server. For production, use PostgreSQL. A SQLite connection can be made without extra packages via Node's built-in driver, or use Prisma for easy migrations. Don't forget to update .env.local with the connection string.
Install the Google Authenticator app from Google Play (Android) or the App Store (iOS). This app is the client that scans QR codes and generates 6-digit TOTP codes. Also enable automatic time sync on your smartphone — TOTP depends on an accurate clock, and this is covered in detail in episode 2.
In Google Authenticator's settings, enable backup to your Google Account. This feature will come in handy when we discuss account recovery in episode 21, and it also builds the habit of backing up your authenticator from the start.
Test the installation with a small script that creates a secret and a TOTP code:
node -e "const { authenticator } = require('otplib'); const s = authenticator.generateSecret(); console.log(s.length, s.slice(0, 4)); console.log(authenticator.generate(s).length);"The first line of output is the length of the Base32 secret and its first four characters, while the second line shows a valid 6-digit TOTP. If both appear without errors, your installation is ready.
So that the examples in this series can be run straight away, arrange your project with a simple structure:
2fa-app/
package.json
.env.local
src/
server.js
db.js
crypto-helper.js
routes/
auth.js
mfa.js
public/
index.htmlThe key separation here is isolating crypto-helper.js (secret encryption logic) and routes/mfa.js (2FA endpoints) from the regular auth routes. We will follow this structure throughout the series so each episode can focus on a single file.
Besides the structure, make sure .env.local is populated from the start with placeholders for the variables we'll fill in gradually: DATABASE_URL, SESSION_SECRET, and MFA_ENCRYPTION_KEY. Never put real values in a file that gets committed to git.
Here's a recap of the pre-requisites you've set up in episode 0:
If anything is still missing, stop and fill the gaps before moving on. A solid foundation will make the next 22 episodes feel much lighter.
In episode 0 you've prepared the footing for the whole series: understanding the JavaScript, basic authentication, and SQL skills required, setting up Node.js 24 LTS, installing otplib, qrcode, and express-rate-limit, and installing Google Authenticator for testing.
The key takeaways:
In the next episode, episode 1, we will cover the history, background, and why you need 2FA — from the evolution of passwords toward passkeys, the birth of HOTP via RFC 4226 and TOTP via RFC 6238, to the reasons why the possession factor beats passwords that can be credential-stuffed. Make sure your Node.js and Google Authenticator are ready, because the Learn 2FA Authentication journey is just beginning!