@sourceregistry/node-totp@1.0.8Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
A zero-dependency, RFC-compliant TOTP (Time-based One-Time Password) library for Node.js. It is intended for server-side 2FA flows with Google Authenticator, Authy, and other TOTP-compatible apps.
@sourceregistry/node-totp
A zero-dependency, RFC-compliant TOTP (Time-based One-Time Password) library for Node.js. It is intended for server-side 2FA flows with Google Authenticator, Authy, and other TOTP-compatible apps.
- RFC 6238 and RFC 4226 compliant
- Zero external dependencies
- Timing attack resistant token comparison
- TypeScript definitions included
- Tested against RFC vectors
- Strict input validation and safe defaults
Installation
npm install @sourceregistry/node-totp
Usage
Basic Example
import { generateURI, verifyToken } from '@sourceregistry/node-totp'; // Generate setup URI for authenticator apps const { uri, secret } = generateURI({ issuer: 'MyApp', account: '[email protected]', algorithm: 'SHA256', digits: 6, period: 30 }); console.log('Scan this URI in your authenticator app:', uri); // otpauth://totp/MyApp:user%40example.com?issuer=MyApp&secret=... // Later, verify user input const userInput = '123456'; const isValid = verifyToken(userInput, secret, { algorithm: 'SHA256', digits: 6, period: 30, window: 1 // Accept tokens from +/-30 seconds }); console.log('Token valid:', isValid);
Advanced Configuration
import totp from '@sourceregistry/node-totp'; // Generate with custom secret length (algorithm-appropriate defaults) const { secret } = totp.generateURI({ issuer: 'SecureApp', account: '[email protected]', algorithm: 'SHA512', // Uses 64-byte secret by default byteLength: 48 // Override default secret length }); // Verify with custom time (useful for testing) const testTime = Math.floor(Date.now() / 1000); const testToken = totp.generateToken( totp.base32.decode(secret), Math.floor(testTime / 30), 6, 'SHA512' ); const isValid = totp.verifyToken(testToken, secret, { algorithm: 'SHA512', digits: 6, period: 30, window: 2, now: testTime // Use specific timestamp instead of Date.now() });
API Reference
generateURI(options)
Generates an otpauth:// URI and a secret for TOTP setup.
issuer(string, required): Service name such asMyAppaccount(string, required): User identifier such as an email addresssecret(string, optional): Canonical unpadded Base32 secretalgorithm(string, optional):SHA1,SHA256, orSHA512(defaultSHA1)digits(number, optional):6,7, or8(default6)period(number, optional): Time step in seconds (default30)byteLength(number, optional): Secret length in bytes
Returns { uri: string, secret: string }.
verifyToken(token, secret, options?)
Verifies a TOTP token against a secret.
token(string): User-provided token with 6 to 8 digitssecret(string): Canonical unpadded Base32 secretoptions.window(number): Time window in steps (default1, meaning +/-30 seconds with the default period)options.period(number): Time step in seconds (default30)options.algorithm(string): Hash algorithm (defaultSHA1)options.digits(number): Expected token length (default6)options.now(number): Unix timestamp in seconds, useful for testing
Returns boolean.
generateToken(secret, counter, digits, algorithm)
Generates a TOTP token.
secret(Buffer): Decoded secret buffercounter(number): Time step counterdigits(number): Token lengthalgorithm(string): Hash algorithm
Returns a zero-padded string token.
base32
RFC 4648 Base32 helpers:
base32.encode(buffer: Buffer): stringbase32.decode(base32Str: string): Buffer
The library accepts canonical unpadded Base32 secrets. Padded or non-canonical forms are normalized or rejected before use.
Security Notes
- Token comparison uses
crypto.timingSafeEqual() - Supported algorithms are limited to
SHA1,SHA256, andSHA512 - Digits are limited to
6,7, or8 - Period must be a positive integer
- Generated secrets use algorithm-appropriate byte lengths
Testing
npm test npm run test:coverage
Examples
QR Code Generation (with qrcode package)
import qrcode from 'qrcode'; import { generateURI } from '@sourceregistry/node-totp'; const { uri } = generateURI({ issuer: 'MyApp', account: '[email protected]' }); const qrDataUrl = await qrcode.toDataURL(uri); // Display qrDataUrl in your HTML template
Express.js Integration
import express from 'express'; import { generateURI, verifyToken } from '@sourceregistry/node-totp'; const app = express(); // Setup route app.get('/2fa/setup', (req, res) => { const { uri, secret } = generateURI({ issuer: 'MyApp', account: req.user.email }); // Store secret securely (encrypted) in user database req.user.totpSecret = secret; res.json({ uri }); }); // Verify route app.post('/2fa/verify', (req, res) => { const { token } = req.body; const isValid = verifyToken(token, req.user.totpSecret, { window: 1 }); res.json({ valid: isValid }); });
License
Apache-2.0 © A.P.A. Slaa
Note: This library is designed for server-side Node.js applications. For browser usage, consider using a Web Crypto API compatible alternative.
Add Package
deno add jsr:@sourceregistry/node-totp
Import symbol
import * as node_totp from "@sourceregistry/node-totp";
Import directly with a jsr specifier
import * as node_totp from "jsr:@sourceregistry/node-totp";