{"id":46142,"library":"redis-otp-manager","title":"redis-otp-manager","description":"Lightweight, Redis-backed OTP (one-time password) manager for Node.js and NestJS applications. Current stable version 1.6.1. Provides production-oriented OTP engine with Redis TTL storage, atomic Redis verification, HMAC hashing with secret rotation support, and abuse-control policies (rate limiting, cooldown, lockout). Includes lifecycle hooks for observability. Supports both ESM and CommonJS. Differentiators: intent-aware keying for multi-purpose OTPs, optional sliding window rate limiting, replay protection for token links, and first-class NestJS module export. Requires Node >=18 and peer dependencies for NestJS integration.","status":"active","version":"1.6.1","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/prakashu51/otp-generator","tags":["javascript","otp","redis","nodejs","nestjs","authentication","security","verification","one-time-password","typescript"],"install":[{"cmd":"npm install redis-otp-manager","lang":"bash","label":"npm"},{"cmd":"yarn add redis-otp-manager","lang":"bash","label":"yarn"},{"cmd":"pnpm add redis-otp-manager","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Redis client adapter for OTP storage","package":"redis","optional":false},{"reason":"NestJS module integration","package":"@nestjs/common","optional":true},{"reason":"NestJS module integration","package":"@nestjs/core","optional":true},{"reason":"NestJS dependency injection metadata","package":"reflect-metadata","optional":true},{"reason":"NestJS reactive extensions","package":"rxjs","optional":true}],"imports":[{"note":"Correct import for ESM or TypeScript. CommonJS users must use destructured require.","wrong":"const OTPManager = require('redis-otp-manager').OTPManager","symbol":"OTPManager","correct":"import { OTPManager } from 'redis-otp-manager'"},{"note":"RedisAdapter is exported from the main package, not a subpath.","wrong":"import { RedisAdapter } from 'redis-otp-manager/adapters'","symbol":"RedisAdapter","correct":"import { RedisAdapter } from 'redis-otp-manager'"},{"note":"NestJS module is exported from a subpath 'redis-otp-manager/nest' to keep main bundle lighter.","wrong":"import { NestOtpManagerModule } from 'redis-otp-manager'","symbol":"NestOtpManagerModule","correct":"import { NestOtpManagerModule } from 'redis-otp-manager/nest'"}],"quickstart":{"code":"import { OTPManager, RedisAdapter } from 'redis-otp-manager';\nimport { createClient } from 'redis';\n\nconst redisClient = createClient({ url: process.env.REDIS_URL ?? 'redis://localhost:6379' });\nawait redisClient.connect();\n\nconst otp = new OTPManager({\n  store: new RedisAdapter(redisClient),\n  ttl: 300,\n  maxAttempts: 3,\n  devMode: false,\n  hashing: {\n    secret: process.env.OTP_HMAC_SECRET ?? 'default-secret',\n  },\n  rateLimit: {\n    window: 60,\n    max: 3,\n  },\n});\n\nconst generated = await otp.generate({\n  type: 'email',\n  identifier: 'user@example.com',\n  intent: 'login',\n});\n\nconsole.log('Generated OTP:', generated.otp);\n\nconst verified = await otp.verify({\n  type: 'email',\n  identifier: 'user@example.com',\n  intent: 'login',\n  otp: generated.otp,\n});\n\nconsole.log('Verified:', verified);\n\nawait redisClient.quit();","lang":"typescript","description":"Shows Redis client initialization, OTPManager construction with HMAC and rate limiting, generation and verification of an OTP."},"warnings":[{"fix":"Wrap your Redis client with new RedisAdapter(redisClient).","message":"In v1.6.0, the `store` option was changed from a direct Redis client to require an adapter (RedisAdapter). Passing a raw Redis client will throw an error.","severity":"breaking","affected_versions":">=1.6.0"},{"fix":"Use cooldown: { seconds: 60 } instead of resendCooldown: 60.","message":"The `resendCooldown` option was deprecated in favor of `cooldown`. In v1.7.0, `resendCooldown` will be removed.","severity":"breaking","affected_versions":">=1.6.0"},{"fix":"Use a secret of 32+ bytes (e.g., crypto.randomBytes(32).toString('hex')).","message":"The `hashing.secret` must be at least 32 bytes (256 bits). Shorter secrets will be silently padded, weakening security.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Set otpLength at initialization and do not change it later for consistency.","message":"The `otpLength` defaults to 6. Changing it after generating OTPs will not affect existing stored OTPs.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Replace resendCooldown with cooldown: { seconds: value }.","message":"In v1.6.0, `resendCooldown` is deprecated. Use `cooldown` instead.","severity":"deprecated","affected_versions":">=1.6.0"}],"env_vars":null,"search_vec":"'1.6.1':23 '18':91 'abus':45 'abuse-control':44 'applic':19 'atom':34 'authent':103 'awar':65 'back':8 'class':85 'commonj':61 'control':46 'cooldown':50 'current':20 'depend':94 'differenti':62 'engin':29 'esm':59 'export':88 'first':84 'first-class':83 'hash':38 'hmac':37 'hook':54 'includ':52 'integr':97 'intent':64 'intent-awar':63 'javascript':98 'key':66 'lifecycl':53 'lightweight':5 'limit':49,76 'link':81 'lockout':51 'manag':4,14 'modul':87 'multi':69 'multi-purpos':68 'nestj':18,86,96,102 'node':90 'node.js':16 'nodej':101 'observ':56 'one':11,107 'one-tim':10 'one-time-password':106 'option':72 'orient':27 'otp':3,9,28,71,99 'password':13,109 'peer':93 'polici':47 'product':26 'production-ori':25 'protect':78 'provid':24 'purpos':70 'rate':48,75 'redi':2,7,31,35,100 'redis-back':6 'redis-otp-manag':1 'replay':77 'requir':89 'rotat':41 'secret':40 'secur':104 'slide':73 'stabl':21 'storag':33 'support':42,57 'time':12,108 'token':80 'ttl':32 'typescript':110 'verif':36,105 'version':22 'window':74","created_at":"2026-06-07T12:58:29.979834+00:00","updated_at":"2026-06-07T12:58:29.979834+00:00","problems":[{"fix":"Ensure redisClient.connect() is called before creating OTPManager. Verify Redis URL.","cause":"Redis client not connected or store not properly initialized.","error":"TypeError: Cannot read properties of undefined (reading 'get')"},{"fix":"Use dynamic import() or switch to CommonJS-compatible imports: const { OTPManager } = require('redis-otp-manager');","cause":"CJS require() on an ESM-only module path.","error":"Error: [ERR_REQUIRE_ESM]: require() of ES Module"},{"fix":"Check that generate() was called with the same type, identifier, and intent. Increase ttl if needed.","cause":"The OTP was never generated, TTL expired, or identifier/intent mismatched.","error":"Error: OTP not found or expired"},{"fix":"Increase rateLimit.max or window, or verify your application logic to avoid excessive calls.","cause":"Too many OTP generation requests within the rate limit window.","error":"Error: Rate limit exceeded. Please try again later."}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://github.com/prakashu51/otp-generator#readme","github":"ssh://git@github.com/prakashu51/otp-generator","docs":null,"changelog":null,"pypi":null,"npm":"redis-otp-manager","openapi_spec":null,"status_page":null,"smithery":null,"categories":["security"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-07","next_check":"2026-09-05","install_tag":null}}