Password Reset and MFALesson 6.3
How to set up TOTP in Node.js with speakeasy
speakeasy package, secret generation, QR code generation, TOTP verification, window parameter, enabling MFA on user record, step-by-step setup flow
Generating and Verifying TOTP
npm install speakeasy qrcode
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');
// Step 1: Generate a secret (called when user starts MFA setup)
const secret = speakeasy.generateSecret({
name: `MyApp (${user.email})`
});
// secret.base32 โ store this temporarily until user confirms
// secret.otpauth_url โ encode as QR code
const qrCodeUrl = await QRCode.toDataURL(secret.otpauth_url);
// Send qrCodeUrl to front end as an
// Step 2: Verify the code the user types to confirm setup
const verified = speakeasy.totp.verify({
secret: secret.base32,
encoding: 'base32',
token: req.body.code,
window: 1 // allow 1 step of clock drift
});
if (verified) {
await db.setUserTotpSecret(user.id, secret.base32);
await db.setMfaEnabled(user.id, true);
res.json({ success: true, backupCodes: generateBackupCodes() });
} else {
res.status(400).json({ error: 'Invalid code, setup failed' });
}
The window: 1 parameter allows codes from the previous and next 30-second window, accommodating small clock drift between the user's device and your server. Do not set it higher than 1โ2 without good reason.
