HMAC-based (HOTP) and Time-based (TOTP) One-Time Password library compatible with Google Authenticator
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The Authenticator class provides Google Authenticator compatible TOTP functionality with Base32 secret encoding. It's the most commonly used component for implementing two-factor authentication in web applications.
Generates a 6-digit TOTP token from a Base32-encoded secret.
/**
* Generate a TOTP token from a Base32 secret
* @param secret - Base32-encoded secret key
* @returns 6-digit token string
*/
generate(secret: string): string;Usage Example:
import { authenticator } from "otplib";
const secret = "KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD";
const token = authenticator.generate(secret);
console.log(token); // "123456"Verifies a token against a secret with configurable time window tolerance.
/**
* Verify a token against a Base32 secret
* @param token - 6-digit token to verify
* @param secret - Base32-encoded secret key
* @returns true if token is valid within time window
*/
check(token: string, secret: string): boolean;
/**
* Object-based token verification
* @param opts - Object containing token and secret
* @returns true if token is valid within time window
*/
verify(opts: { token: string; secret: string }): boolean;Usage Examples:
import { authenticator } from "otplib";
const secret = "KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD";
const token = "123456";
// Method 1: Direct parameters
const isValid = authenticator.check(token, secret);
// Method 2: Object parameters
const isValid2 = authenticator.verify({ token, secret });
console.log(isValid); // true or falseGenerates cryptographically secure Base32-encoded secrets for new users.
/**
* Generate a random Base32 secret key
* @param numberOfBytes - Number of random bytes (default: 10)
* @returns Base32-encoded secret string
*/
generateSecret(numberOfBytes?: number): string;Usage Example:
import { authenticator } from "otplib";
// Generate with default length (10 bytes = 16 Base32 characters)
const secret = authenticator.generateSecret();
console.log(secret); // "JBSWY3DPEHPK3PXP"
// Generate with custom length
const longSecret = authenticator.generateSecret(20);
console.log(longSecret); // Longer Base32 stringCreates otpauth:// URIs for QR code generation, compatible with Google Authenticator and other apps.
/**
* Generate an otpauth URI for QR code creation
* @param accountName - User identifier (usually email)
* @param issuer - Service name
* @param secret - Base32-encoded secret
* @returns otpauth:// URI string
*/
keyuri(accountName: string, issuer: string, secret: string): string;Usage Example:
import { authenticator } from "otplib";
import QRCode from "qrcode";
const secret = authenticator.generateSecret();
const user = "user@example.com";
const service = "My App";
const otpauth = authenticator.keyuri(user, service, secret);
console.log(otpauth);
// "otpauth://totp/My%20App:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=My%20App"
// Generate QR code
QRCode.toDataURL(otpauth, (err, imageUrl) => {
if (!err) {
console.log(imageUrl); // Data URL for QR code image
}
});Check token with detailed timing information for debugging and advanced use cases.
/**
* Check token with timing delta information
* @param token - Token to verify
* @param secret - Base32 secret
* @returns Delta value: 0 = exact match, negative = past window, positive = future window, null = invalid
*/
checkDelta(token: string, secret: string): number | null;Usage Example:
import { authenticator } from "otplib";
const secret = "KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD";
const token = "123456";
const delta = authenticator.checkDelta(token, secret);
if (delta === 0) {
console.log("Token is from current time window");
} else if (delta && delta < 0) {
console.log(`Token is from ${Math.abs(delta)} time window(s) ago`);
} else if (delta && delta > 0) {
console.log(`Token is from ${delta} time window(s) in the future`);
} else {
console.log("Token is invalid");
}Convert between raw secret keys and Base32 encoding.
/**
* Encode a raw secret to Base32
* @param secret - Raw secret key
* @returns Base32-encoded string
*/
encode(secret: string): string;
/**
* Decode a Base32 secret to raw format
* @param secret - Base32-encoded secret
* @returns Raw secret key
*/
decode(secret: string): string;Usage Example:
import { authenticator } from "otplib";
const rawSecret = "hello world";
const base32Secret = authenticator.encode(rawSecret);
console.log(base32Secret); // "NBSWY3DPEB3W64TMMQ======"
const decoded = authenticator.decode(base32Secret);
console.log(decoded); // "hello world"Manage instance-level configuration options.
/**
* Get/set configuration options
*/
options: Partial<AuthenticatorOptions>;
/**
* Reset options to default values
*/
resetOptions(): void;
/**
* Get all options with defaults applied
* @returns Complete options object
*/
allOptions(): Readonly<AuthenticatorOptions>;Usage Example:
import { authenticator } from "otplib";
// View current options
console.log(authenticator.options);
// Modify options
authenticator.options = { digits: 8, step: 60 };
// Reset to defaults
authenticator.resetOptions();
// Get complete options with defaults
const fullOptions = authenticator.allOptions();
console.log(fullOptions.digits); // 6 (default)interface AuthenticatorOptions extends TOTPOptions {
keyEncoder: (secret: string, encoding: string) => string;
keyDecoder: (secret: string, encoding: string) => string;
createRandomBytes: (size: number, encoding: string) => string;
}
interface TOTPOptions extends HOTPOptions {
epoch: number;
step: number;
window: number | [number, number];
}
interface HOTPOptions {
algorithm: 'sha1' | 'sha256' | 'sha512';
digits: number;
encoding: 'ascii' | 'base64' | 'hex' | 'latin1' | 'utf8';
createDigest: (algorithm: string, key: string, data: string) => string;
createHmacKey: (algorithm: string, secret: string, encoding: string) => string;
}Install with Tessl CLI
npx tessl i tessl/npm-otplib