npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

redis-otp-manager

v1.6.1

Published

Lightweight, Redis-backed OTP manager for Node.js apps

Readme

redis-otp-manager

Lightweight, Redis-backed OTP manager for Node.js and NestJS apps.

redis-otp-manager gives you a production-focused OTP engine with Redis TTL storage, atomic Redis verification, cryptographic hardening, observability hooks, and abuse-control policies without forcing a delivery provider.

Why Use It

  • Redis-backed OTP storage with TTL cleanup
  • Atomic Redis generate and verify paths
  • HMAC hashing with secret rotation support
  • Cooldown, rate limiting, and lockout controls
  • Hook-based observability with metadata context
  • Works with plain Node.js and NestJS
  • Supports both ESM and CommonJS consumers

Install

npm install redis-otp-manager

Quick Start

import { OTPManager, RedisAdapter } from "redis-otp-manager";
import { createClient } from "redis";

const redisClient = createClient({ url: process.env.REDIS_URL });
await redisClient.connect();

const otp = new OTPManager({
  store: new RedisAdapter(redisClient),
  ttl: 300,
  maxAttempts: 3,
  devMode: false,
  hashing: {
    secret: process.env.OTP_HMAC_SECRET,
  },
  rateLimit: {
    window: 60,
    max: 3,
  },
});

const generated = await otp.generate({
  type: "email",
  identifier: "[email protected]",
  intent: "login",
});

await otp.verify({
  type: "email",
  identifier: "[email protected]",
  intent: "login",
  otp: "123456",
});

Feature Overview

Core Flows

  • OTP generation and verification
  • Verification token generation and verification
  • Intent-aware keying
  • In-memory adapter for tests
  • NestJS module export via redis-otp-manager/nest

Security

  • Keyed HMAC support through hashing.secret
  • Secret rotation with previousSecrets
  • Legacy SHA-256 verification support for migrations
  • Atomic Redis verification to prevent double-success races

Abuse Controls

  • Cooldown policy support
  • Fixed-window and Redis sliding-window rate limiting
  • Scoped throttling by identifier, intent, channel, or intent + channel
  • Temporary lock windows after repeated failed verification attempts
  • Optional replay detection for already-used token verification links

Observability

  • Lifecycle hooks for generated, verified, failed, locked, rate-limited, and cooldown-blocked events
  • Additive credentialKind in hook payloads so OTP and token flows are distinguishable
  • Request-scoped metadata passed to hook payloads
  • Non-blocking hook error handling by default

Examples

Configuration

OTPManager options

type OTPManagerOptions = {
  store: StoreAdapter;
  ttl: number;
  maxAttempts: number;
  otpLength?: number;
  devMode?: boolean;
  resendCooldown?: number;
  cooldown?: {
    seconds: number;
    scope?: "identifier" | "intent" | "channel" | "intent_channel";
  };
  rateLimit?: {
    window: number;
    max: number;
    scope?: "identifier" | "intent" | "channel" | "intent_channel";
    algorithm?: "fixed_window" | "sliding_window";
  };
  lockout?: {
    seconds: number;
    afterAttempts: number;
    appliesTo?: "verify" | "generate" | "both";
    scope?: "identifier" | "intent" | "channel" | "intent_channel";
  };
  hashing?: {
    secret?: string;
    previousSecrets?: string[];
    allowLegacyVerify?: boolean;
  };
  replayProtection?: {
    enabled: boolean;
    ttl: number;
    scope?: "identifier" | "intent" | "channel" | "intent_channel";
  };
};

Backward compatibility notes

  • resendCooldown still works and remains supported.
  • cooldown is the richer replacement for policy-based cooldown configuration.
  • legacy SHA-256 verification is still supported by default when migrating to HMAC.
  • CommonJS and ESM consumers are both supported.

Config precedence

  • cooldown takes precedence over legacy resendCooldown when both are provided.
  • rateLimit.scope defaults to channel.
  • rateLimit.algorithm defaults to fixed_window.
  • lockout.appliesTo defaults to both.
  • lockout.scope defaults to intent_channel.
  • hooks.throwOnError defaults to non-blocking behavior unless explicitly set to true.
  • replayProtection is opt-in and only affects token verification flow.

Stable API

v1.0.0 is the first stable production release of redis-otp-manager.

The following public surface is considered stable:

  • OTPManager
  • RedisAdapter
  • MemoryAdapter
  • exported error classes
  • exported hook and config types
  • redis-otp-manager/nest

Full stability notes: docs/stability.md

Error Reference

The package can throw these errors:

  • OTPRateLimitExceededError
  • OTPExpiredError
  • OTPInvalidError
  • VerificationSecretExpiredError
  • VerificationSecretInvalidError
  • VerificationSecretAlreadyUsedError
  • OTPMaxAttemptsExceededError
  • OTPResendCooldownError
  • OTPLockedError

Detailed behavior reference: docs/errors.md

Production Recommendations

  • keep devMode: false in production
  • use hashing.secret in production
  • prefer RedisAdapter in production
  • keep Redis private and never publicly exposed
  • use HTTPS for all OTP or token delivery flows
  • keep maxAttempts low, typically 3
  • enable cooldown and rate limiting for public endpoints
  • use lockout windows for abuse-heavy flows

More guidance: docs/production.md

Migration Guides

Version-to-version migration notes live in docs/migrations.md.

Reliability And Compatibility

Current package validation includes:

  • real Redis integration tests against a live Redis server
  • Redis-backed CI validation for TTL, lockout, cooldown, and sliding-window behavior
  • ESM and CommonJS smoke checks against the built package output
  • Nest integration smoke coverage in CI

Tested Scenarios

The package is currently validated for:

  • in-memory unit and behavior tests
  • fake Redis atomic behavior tests
  • real Redis integration tests in CI
  • NestJS provider smoke coverage
  • ESM and CommonJS package smoke checks

Feedback And Support

If you run into a bug, unexpected behavior, or have a feature request, open an issue here:

  • Bug reports: https://github.com/prakashu51/otp-generator/issues
  • Feature requests: https://github.com/prakashu51/otp-generator/issues

When reporting, please include:

  • package version
  • Node.js version
  • adapter used (RedisAdapter or MemoryAdapter)
  • minimal reproduction steps
  • expected behavior and actual behavior

Adapters

Use auditAdapter and deliveryAdapter when you want provider-agnostic integration points without changing the existing OTP or token core flow.

const otp = new OTPManager({
  store: new RedisAdapter(redisClient),
  ttl: 300,
  maxAttempts: 3,
  deliveryAdapter: {
    async send(payload) {
      console.log("send", payload);
    },
  },
  auditAdapter: {
    async record(event) {
      console.log("audit", event);
    },
  },
});

await otp.generateAndSend({
  type: "email",
  identifier: "[email protected]",
  intent: "login",
});

await otp.generateTokenAndSend(
  {
    type: "email",
    identifier: "[email protected]",
    intent: "verify-email",
  },
  {
    baseUrl: "https://app.example.com/verify-email",
  },
);

Token Flow

Use generateToken() and verifyToken() when you want email verification links or magic-link style flows without changing the existing OTP API.

Token verification returns token-friendly generic secret errors such as VerificationSecretExpiredError and VerificationSecretInvalidError, while the OTP flow keeps the original OTP error classes.

If you enable replayProtection, successful token verification stores a short-lived used marker so repeated verification can return VerificationSecretAlreadyUsedError instead of the generic expired/nonexistent response.

const generated = await otp.generateToken({
  type: "email",
  identifier: "[email protected]",
  intent: "verify-email",
});

await otp.verifyToken({
  type: "email",
  identifier: "[email protected]",
  intent: "verify-email",
  token: generated.token ?? "",
});

const replayAwareOtp = new OTPManager({
  store: new RedisAdapter(redisClient),
  ttl: 1800,
  maxAttempts: 3,
  replayProtection: {
    enabled: true,
    ttl: 3600,
    scope: "intent_channel",
  },
});

Post-1.0.0 Roadmap

  • Framework-specific callback and redirect examples
  • Provider-specific companion packages and adapters
  • Richer token and verification-link workflow helpers