Documentation
Complete guide to integrating modern-totp in your JavaScript applications.
Installation
Install modern-totp using your preferred package manager:
npm install modern-totp
# or
yarn add modern-totp
# or
pnpm add modern-totpBasic Usage
Get started with TOTP authentication in three simple steps:
import { generateSecret, generateTOTP, verifyTOTP } from 'modern-totp';
// 1. Generate a secret for the user (store this securely)
const secret = generateSecret();
console.log(secret); // "JBSWY3DPEHPK3PXP"
// 2. Generate a TOTP code
const token = generateTOTP(secret);
console.log(token); // "123456"
// 3. Verify the TOTP code
const isValid = verifyTOTP(token, secret);
console.log(isValid); // trueQR Code Integration
Generate QR codes for easy setup with authenticator apps:
import { generateSecret, generateQRCodeURL } from 'modern-totp';
import QRCode from 'qrcode'; // Use with QR code library
const secret = generateSecret();
const issuer = 'MyApp';
const accountName = 'user@example.com';
// Generate QR code URL
const qrCodeURL = generateQRCodeURL(secret, issuer, accountName);
QRCode.toDataURL(qrCodeURL, (err, url) => {
// Display the QR code to the user
document.getElementById('qr-code').src = url;
});API Reference
generateSecret(length?: number): string
Generates a cryptographically secure random secret for TOTP generation.
Parameters:
length(optional): Length of the secret in bytes. Default: 20
Returns: Base32-encoded secret string
generateTOTP(secret: string, options?: TOTPOptions): string
Generates a TOTP code for the given secret.
Parameters:
secret: Base32-encoded secret stringoptions(optional): TOTP configuration options
Returns: 6-digit TOTP code
verifyTOTP(token: string, secret: string, options?: TOTPOptions): boolean
Verifies a TOTP code against the given secret.
Parameters:
token: TOTP code to verifysecret: Base32-encoded secret stringoptions(optional): TOTP configuration options
Returns: true if valid, false otherwise
generateQRCodeURL(secret: string, issuer: string, accountName: string): string
Generates a QR code URL for authenticator app setup.
Parameters:
secret: Base32-encoded secret stringissuer: Your application nameaccountName: User identifier (usually email)
Returns: otpauth:// URL for QR code generation
Advanced Configuration
import { generateTOTP, verifyTOTP, generateSecret } from 'modern-totp';
// Custom time step and digits
const options = {
timeStep: 30, // 30 seconds (default)
digits: 6, // 6 digits (default)
algorithm: 'SHA1' // SHA1 (default)
};
const secret = generateSecret(32); // 32 byte secret
const token = generateTOTP(secret, options);
const isValid = verifyTOTP(token, secret, options);Framework Examples
Next.js API Routes
// pages/api/auth/setup-2fa.js
import { generateSecret, generateQRCodeURL } from 'modern-totp';
export default function handler(req, res) {
if (req.method === 'POST') {
const { email } = req.body;
// Generate secret for user
const secret = generateSecret();
// Store secret in database (encrypted)
await saveUserSecret(email, secret);
// Generate QR code URL
const qrCodeURL = generateQRCodeURL(secret, 'MyApp', email);
res.json({ qrCodeURL, secret });
}
}
// pages/api/auth/verify-2fa.js
import { verifyTOTP } from 'modern-totp';
export default function handler(req, res) {
if (req.method === 'POST') {
const { email, token } = req.body;
// Get user secret from database
const secret = await getUserSecret(email);
// Verify TOTP
const isValid = verifyTOTP(token, secret);
if (isValid) {
// Create session or JWT token
res.json({ success: true });
} else {
res.status(401).json({ error: 'Invalid token' });
}
}
}React Component
import React, { useState, useEffect } from 'react';
import { generateTOTP } from 'modern-totp';
function TOTPDisplay({ secret }) {
const [token, setToken] = useState('');
const [timeLeft, setTimeLeft] = useState(30);
useEffect(() => {
const updateToken = () => {
const newToken = generateTOTP(secret);
setToken(newToken);
};
const updateTimer = () => {
const now = Date.now();
const timeStep = 30000; // 30 seconds
const timeLeft = timeStep - (now % timeStep);
setTimeLeft(Math.ceil(timeLeft / 1000));
};
updateToken();
updateTimer();
const interval = setInterval(() => {
updateToken();
updateTimer();
}, 1000);
return () => clearInterval(interval);
}, [secret]);
return (
<div>
<div className="totp-code">{token}</div>
<div className="timer">Expires in {timeLeft}s</div>
</div>
);
}Security Best Practices
Secure Secret Storage
Always encrypt TOTP secrets before storing them in your database. Never store secrets in plain text.
// ❌ Bad
const secret = generateSecret();
await db.users.update({ id }, { totpSecret: secret });
// ✅ Good
const secret = generateSecret();
const encryptedSecret = encrypt(secret, process.env.ENCRYPTION_KEY);
await db.users.update({ id }, { totpSecret: encryptedSecret });Rate Limiting
Implement rate limiting for TOTP verification attempts to prevent brute force attacks.
// Limit to 3 attempts per minute per user
const attempts = await redis.get(`totp_attempts:${userId}`);
if (attempts && attempts > 3) {
throw new Error('Too many attempts. Try again later.');
}
const isValid = verifyTOTP(token, secret);
if (!isValid) {
await redis.incr(`totp_attempts:${userId}`);
await redis.expire(`totp_attempts:${userId}`, 60);
}Backup Codes
Always provide backup codes for account recovery in case the user loses access to their authenticator.
// Generate backup codes during 2FA setup
const backupCodes = Array.from({ length: 10 }, () =>
generateSecret(8).replace(/[^A-Z0-9]/g, '')
);
// Hash and store backup codes
const hashedCodes = backupCodes.map(code => bcrypt.hash(code, 10));
await db.users.update({ id }, { backupCodes: hashedCodes });⚠️ Important Security Notes
- Never expose TOTP secrets in client-side code
- Use HTTPS for all authentication endpoints
- Implement proper session management
- Consider time window tolerance for network delays
- Log authentication attempts for security monitoring