Skip to content

Security Best Practices

Guidelines for securely implementing OTP-based authentication with otplib.

Secret Generation

Always use cryptographically secure random number generation. otplib's generateSecret uses a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) internally.

typescript
// UNSAFE: Predictable values
const secret = "AAAAAAAAAAAAAAAA";
const secret = "user123secret";

// UNSAFE: Weak random sources
const secret = Math.random().toString(36);
const secret = Date.now().toString();

Token Verification

Constant-Time Comparison

otplib uses constant-time comparison internally to prevent timing attacks.

typescript
// UNSAFE: Vulnerable to timing attacks
if (generatedToken === userToken) {
  // ...
}

Rate Limiting

This library does not implement rate limiting and is focus on providing OTP functionality. Do implement rate limiting in your application to prevent brute-force attacks.

Replay Attack Prevention

otplib is a stateless library. It does not track which tokens have already been verified.

HOTP

Always increment the counter after successful verification.

typescript
if (result.valid) {
  // Remember to implement a counter increment function
  // to prevent replay
  await updateCounter(counter + result.delta + 1);
  grantAccess();
}

TOTP

Consider implementing stateful tracking in your application database or cache to prevent replay attacks. Without this, a valid token can be reused multiple times within its validity window.

Other Common Vulnerabilities

Secret Exposure in Logs

typescript
// UNSAFE: Exposes secret in logs
console.log("Verifying token for secret:", secret);

Large Verification Windows

typescript
// UNSAFE: Large verification windows allow replay attacks
const result = await verify({ secret, token, epochTolerance: 300 });
typescript
// SAFER: Small verification windows prevent replay attacks
const result = await verify({ secret, token, epochTolerance: 30 });

Further Reading

Released under the MIT License.