Node One Time Password library, supports HOTP, TOTP and works with Google Authenticator
npx @tessl/cli install tessl/npm-notp@2.0.0Node One Time Password library that provides fast, zero-dependency implementations of HOTP (counter-based) and TOTP (time-based) one time password algorithms. Fully compliant with RFC 4226 and RFC 6238, and compatible with Google Authenticator and other OTP applications.
npm install notpconst notp = require('notp');For ES modules:
import * as notp from 'notp';const notp = require('notp');
// Generate TOTP token (most common use case)
const secret = 'user_secret_key';
const token = notp.totp.gen(secret);
console.log('Current TOTP token:', token);
// Verify TOTP token
const userToken = '123456'; // Token from user's authenticator app
const verification = notp.totp.verify(userToken, secret);
if (verification) {
console.log('Token valid, delta:', verification.delta);
} else {
console.log('Token invalid');
}
// Generate HOTP token (counter-based)
const counter = 1;
const hotpToken = notp.hotp.gen(secret, { counter: counter });
// Verify HOTP token
const hotpVerification = notp.hotp.verify(hotpToken, secret, { counter: counter });Generate counter-based One Time Passwords following RFC 4226.
/**
* Generate a counter based One Time Password
* @param {string} key - Secret key for OTP generation (should be unique per user)
* @param {Object} opt - Options object
* @param {number} opt.counter - Counter value for HOTP generation (default: 0)
* @returns {string} - 6-digit OTP token
*/
hotp.gen(key, opt)Usage Example:
const notp = require('notp');
// Generate HOTP with counter
const secret = 'shared_secret_key';
const options = { counter: 5 };
const token = notp.hotp.gen(secret, options);
console.log('HOTP Token:', token); // e.g., "254676"Verify counter-based One Time Passwords with configurable drift tolerance.
/**
* Verify a counter based One Time Password
* @param {string} token - The OTP token to verify
* @param {string} key - Secret key used for verification
* @param {Object} opt - Options object
* @param {number} opt.window - Allowable margin for counter drift (default: 50)
* @param {number} opt.counter - Current counter value (default: 0)
* @returns {Object|null} - Returns {delta: number} on success, null on failure
*/
hotp.verify(token, key, opt)Usage Example:
const notp = require('notp');
const secret = 'shared_secret_key';
const userToken = '254676';
const options = {
counter: 5,
window: 10 // Check 10 positions forward/backward
};
const result = notp.hotp.verify(userToken, secret, options);
if (result) {
console.log('Token valid, counter delta:', result.delta);
// Update stored counter based on delta
} else {
console.log('Token invalid');
}Generate time-based One Time Passwords following RFC 6238.
/**
* Generate a time based One Time Password
* @param {string} key - Secret key for OTP generation (should be unique per user)
* @param {Object} opt - Options object
* @param {number} opt.time - Time step in seconds (default: 30)
* @param {number} opt._t - Override current time (test environments only)
* @returns {string} - 6-digit OTP token
*/
totp.gen(key, opt)Usage Example:
const notp = require('notp');
// Generate TOTP with default 30-second time step
const secret = 'shared_secret_key';
const token = notp.totp.gen(secret);
console.log('Current TOTP token:', token);
// Generate TOTP with custom time step
const customToken = notp.totp.gen(secret, { time: 60 }); // 60-second intervals
console.log('TOTP with 60s intervals:', customToken);Verify time-based One Time Passwords with configurable time drift tolerance.
/**
* Verify a time based One Time Password
* @param {string} token - The OTP token to verify
* @param {string} key - Secret key used for verification
* @param {Object} opt - Options object
* @param {number} opt.window - Allowable margin for time drift (default: 6)
* @param {number} opt.time - Time step in seconds (default: 30)
* @param {number} opt._t - Override current time (test environments only)
* @returns {Object|null} - Returns {delta: number} on success, null on failure
*/
totp.verify(token, key, opt)Usage Example:
const notp = require('notp');
const secret = 'shared_secret_key';
const userToken = '123456'; // From user's authenticator app
const options = {
window: 2, // Check 2 time steps forward/backward
time: 30 // 30-second time steps
};
const result = notp.totp.verify(userToken, secret, options);
if (result) {
console.log('Token valid, time delta:', result.delta);
} else {
console.log('Token invalid or expired');
}/**
* HOTP (counter-based OTP) module
*/
const hotp = {
gen: function(key, opt),
verify: function(token, key, opt)
};/**
* TOTP (time-based OTP) module
*/
const totp = {
gen: function(key, opt),
verify: function(token, key, opt)
};/**
* HOTP options
*/
interface HOTPOptions {
counter?: number; // Counter value (default: 0)
window?: number; // Verification window (default: 50)
}
/**
* TOTP options
*/
interface TOTPOptions {
time?: number; // Time step in seconds (default: 30)
window?: number; // Verification window (default: 6)
_t?: number; // Time override (test only)
}
/**
* Verification result
*/
interface VerificationResult {
delta: number; // Counter/time step difference
}For Google Authenticator compatibility, secret keys must be base32 encoded. The notp library does not provide base32 encoding - use the separate thirty-two package:
const notp = require('notp');
const base32 = require('thirty-two');
// Encode secret for Google Authenticator
const secret = 'user_secret_key';
const encoded = base32.encode(secret);
const googleSecret = encoded.toString().replace(/=/g, ''); // Remove padding
// Generate QR code URI
const uri = `otpauth://totp/MyApp:user@example.com?secret=${googleSecret}&issuer=MyApp`;
// Generate token (same as normal usage)
const token = notp.totp.gen(secret);The library throws errors in specific cases:
_t option outside test environment (NODE_ENV !== 'test')// Error handling example
try {
const token = notp.totp.gen(secret, { _t: Date.now() }); // Throws in production
} catch (error) {
console.error('Cannot override time in non-test environment');
}
// Verification returns null on failure
const result = notp.totp.verify('invalid', secret);
if (result === null) {
console.log('Verification failed');
}