High-performance TOTP (Time-based One-Time Password) library using native Web Crypto API
A lightweight, RFC 6238 compliant TOTP implementation built with TypeScript and Web Crypto API. Perfect for generating and verifying time-based one-time passwords in both browser and Node.js environments.
- π Native Performance - Uses Web Crypto API for optimal performance
- π RFC 6238 Compliant - Follows official TOTP specification
- π¦ Zero Dependencies - No external dependencies required
- π§ TypeScript Support - Full TypeScript definitions included
- π Universal - Works in browsers and Node.js (16+)
- β‘ Lightweight - Minimal bundle size
- π― Dual API - Both class-based and static methods
- π Multiple Algorithms - SHA-1, SHA-256, SHA-512 support
- π± Google Authenticator Compatible - Standard URI format
npm install totp-nativeyarn add totp-nativepnpm add totp-nativeimport { TotpGenerator } from 'totp-native';
// Create a generator instance
const totp = new TotpGenerator({
secret: 'JBSWY3DPEHPK3PXP'
});
// Generate current TOTP token
const token = await totp.generate();
console.log(`Current TOTP: ${token}`); // e.g., "123456"
// Verify a token
const isValid = await totp.verify('123456');
console.log(`Token valid: ${isValid}`);import { Totp } from 'totp-native';
// Generate token directly
const token = await Totp.generate('JBSWY3DPEHPK3PXP');
// Verify token directly
const isValid = await Totp.verify('JBSWY3DPEHPK3PXP', '123456');interface TotpConfig {
secret: string; // Base32 encoded secret (required)
digits?: number; // Token length 4-8 (default: 6)
period?: number; // Time step in seconds (default: 30)
algorithm?: 'SHA1' | 'SHA256' | 'SHA512'; // Hash algorithm (default: SHA1)
skew?: number; // Clock skew tolerance (default: 1)
explicitZeroPad?: boolean; // Zero padding (default: true)
timestamp?: number; // Custom timestamp in ms (default: current time)
}// 8-digit tokens with SHA-256
const totp = new TotpGenerator({
secret: 'JBSWY3DPEHPK3PXP',
digits: 8,
algorithm: 'SHA256'
});
// 60-second period with higher skew tolerance
const totp = new TotpGenerator({
secret: 'JBSWY3DPEHPK3PXP',
period: 60,
skew: 2
});
// Generate token for specific timestamp
const token = await totp.generateAt(1640995200);// Generate cryptographically secure random secret
const secret = TotpGenerator.generateSecret();
console.log(secret); // e.g., "JBSWY3DPEHPK3PXP"
// Custom length (default: 32 bytes)
const longSecret = TotpGenerator.generateSecret(64);const totp = new TotpGenerator({ secret: 'JBSWY3DPEHPK3PXP' });
// Generate QR code compatible URI
const uri = totp.generateUri('MyApp', 'user@example.com');
console.log(uri);
// otpauth://totp/MyApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=MyApp...
// Parse existing URI
const config = TotpGenerator.parseUri(uri);// Get remaining seconds in current time window
const remaining = Totp.getRemainingTime(30);
console.log(`Token expires in ${remaining} seconds`);
// Verify with custom time skew
const isValid = await totp.verifyWithSkew('123456', 2);class TotpGenerator {
constructor(config: TotpConfig)
// Instance methods
async generate(): Promise<string>
async generateAt(timestamp: number): Promise<string>
async verify(token: string): Promise<boolean>
async verifyWithSkew(token: string, skew: number): Promise<boolean>
generateUri(issuer: string, accountName: string): string
// Static methods
static generateSecret(length?: number): string
static parseUri(uri: string): TotpConfig
}class Totp {
static async generate(secret: string, options?: Partial<TotpConfig>): Promise<string>
static async generateAt(secret: string, timestamp: number, options?: Partial<TotpConfig>): Promise<string>
static async verify(secret: string, token: string, options?: Partial<TotpConfig>): Promise<boolean>
static async verifyWithSkew(secret: string, token: string, skew: number, options?: Partial<TotpConfig>): Promise<boolean>
static generateSecret(length?: number): string
static parseUri(uri: string): TotpConfig
static createUri(secret: string, issuer: string, accountName: string, options?: Partial<TotpConfig>): string
static getRemainingTime(period?: number): number
}import { TotpError } from 'totp-native';
try {
const totp = new TotpGenerator({ secret: 'INVALID!' });
await totp.generate();
} catch (error) {
if (error instanceof TotpError) {
console.log(`TOTP Error: ${error.message}`);
console.log(`Error Code: ${error.code}`);
}
}MISSING_SECRET- Secret is requiredINVALID_DIGITS- Digits must be between 4 and 8INVALID_PERIOD- Period must be greater than 0INVALID_SKEW- Skew must be non-negativeINVALID_BASE32- Invalid Base32 character in secretINVALID_URI- Invalid TOTP URI formatPARSE_ERROR- Failed to parse URIGENERATION_ERROR- Failed to generate TOTP
- Node.js: 16.0.0+
- Browsers: Modern browsers with Web Crypto API support
- TypeScript: 4.0+
- Minified: ~15KB
- Gzipped: ~5KB
- Zero dependencies
npm test # Run tests
npm run test:coverage # Run with coverage
npm run test:watch # Watch modenpm run build # Build library
npm run dev # Watch mode
npm run lint # Lint code
npm run lint:fix # Fix lint issuesimport { TotpGenerator } from 'totp-native';
import QRCode from 'qrcode';
// Generate secret and QR code
const secret = TotpGenerator.generateSecret();
const totp = new TotpGenerator({ secret });
const uri = totp.generateUri('MyApp', 'user@example.com');
// Generate QR code
const qrCodeUrl = await QRCode.toDataURL(uri);
console.log(`Show this QR code to user: ${qrCodeUrl}`);import { Totp } from 'totp-native';
function totpMiddleware(req, res, next) {
const { token, secret } = req.body;
Totp.verify(secret, token)
.then(isValid => {
if (isValid) {
next();
} else {
res.status(401).json({ error: 'Invalid TOTP token' });
}
})
.catch(error => {
res.status(500).json({ error: 'TOTP verification failed' });
});
}Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.
- totp-turbo - Rust + WASM implementation
- RFC 6238 - TOTP specification
Built with β€οΈ using Web Crypto API