
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@sourceregistry/node-totp
Advanced tools
Node.js TOTP library for generating otpauth URIs and verifying time-based one-time passwords
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.
npm install @sourceregistry/node-totp
import { generateURI, verifyToken } from '@sourceregistry/node-totp';
// Generate setup URI for authenticator apps
const { uri, secret } = generateURI({
issuer: 'MyApp',
account: 'user@example.com',
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);
import totp from '@sourceregistry/node-totp';
// Generate with custom secret length (algorithm-appropriate defaults)
const { secret } = totp.generateURI({
issuer: 'SecureApp',
account: 'admin@secureapp.com',
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()
});
generateURI(options)Generates an otpauth:// URI and a secret for TOTP setup.
issuer (string, required): Service name such as MyAppaccount (string, required): User identifier such as an email addresssecret (string, optional): Canonical unpadded Base32 secretalgorithm (string, optional): SHA1, SHA256, or SHA512 (default SHA1)digits (number, optional): 6, 7, or 8 (default 6)period (number, optional): Time step in seconds (default 30)byteLength (number, optional): Secret length in bytesReturns { 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 (default 1, meaning +/-30 seconds with the default period)options.period (number): Time step in seconds (default 30)options.algorithm (string): Hash algorithm (default SHA1)options.digits (number): Expected token length (default 6)options.now (number): Unix timestamp in seconds, useful for testingReturns boolean.
generateToken(secret, counter, digits, algorithm)Generates a TOTP token.
secret (Buffer): Decoded secret buffercounter (number): Time step counterdigits (number): Token lengthalgorithm (string): Hash algorithmReturns a zero-padded string token.
base32RFC 4648 Base32 helpers:
base32.encode(buffer: Buffer): stringbase32.decode(base32Str: string): BufferThe library accepts canonical unpadded Base32 secrets. Padded or non-canonical forms are normalized or rejected before use.
crypto.timingSafeEqual()SHA1, SHA256, and SHA5126, 7, or 8npm test
npm run test:coverage
qrcode package)import qrcode from 'qrcode';
import { generateURI } from '@sourceregistry/node-totp';
const { uri } = generateURI({
issuer: 'MyApp',
account: 'user@example.com'
});
const qrDataUrl = await qrcode.toDataURL(uri);
// Display qrDataUrl in your HTML template
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 });
});
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.
FAQs
Node.js TOTP library for generating otpauth URIs and verifying time-based one-time passwords
We found that @sourceregistry/node-totp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.