Implement OTP Verification with Node.js, Express, and Plivo - code-examples -

Frequently Asked Questions

Set up a Node.js project with Express, install the Plivo Node.js SDK, configure Redis for OTP storage, and implement API endpoints for requesting and verifying OTPs. Use environment variables to securely manage Plivo credentials and other sensitive information. Follow the detailed step-by-step instructions provided in the guide for a complete implementation.
Redis acts as a fast, in-memory data store for temporarily storing OTPs. Its ability to set expiration times (TTL) on keys is crucial for automatically deleting expired OTPs. The system uses the phone number as a key and the generated OTP as the value in Redis.
Plivo is a cloud communication platform offering a reliable and easy-to-use SMS API. The official Plivo Node.js SDK simplifies integration with your Node.js application and enables global SMS delivery for OTP verification.
Rate limiting is essential for all production OTP systems to prevent abuse and brute-force attacks. Implement rate limiting middleware, like express-rate-limit, to restrict the number of OTP requests and verifications from a single IP address within a specific time window (e.g., 10 requests per 5 minutes).
Yes, you can customize both the length and expiry time. These are set using the OTP_LENGTH and OTP_EXPIRY_SECONDS environment variables. The code provides default values of 6 digits for length and 300 seconds (5 minutes) for expiry.
The provided code uses `crypto.randomInt()` for generating cryptographically secure random numeric OTPs. This is the preferred method for production environments due to its higher security compared to using `Math.random()`. A fallback mechanism using Math.random is also included in case of errors.
You need Node.js v14 or later, npm or yarn, a Plivo account with an SMS-enabled number and sufficient credits, a running Redis instance (local or cloud), basic understanding of Node.js and Express, and a tool for making API requests (Postman, Insomnia, etc.).
Storing sensitive credentials directly in your code is a security risk. Using a .env file and the dotenv library keeps these values separate from your source code. Never commit your .env file to version control.
The submitted OTP is compared to the value stored in Redis associated with the user's phone number. If the codes match and haven't expired, the verification is successful, and the OTP in Redis is immediately deleted to prevent reuse.
The client requests an OTP, the server generates and stores it in Redis, and Plivo sends it via SMS. The client submits the OTP and the server verifies it against the Redis value. Node.js/Express, Redis, and Plivo are core system components.
Create directories for source code (src), initialize npm, and create files for application logic (app.js, config.js, otp.service.js, routes.js), environment variables (.env), and .gitignore. This structure helps organize the project effectively.
Implement comprehensive error handling in both service and API layers, log errors with context, and utilize appropriate HTTP status codes (4xx/5xx for client and server errors respectively). Use specific error messages without revealing sensitive data.
Use a dedicated logging library like Winston or Pino for structured logging (JSON format), different log levels (info, warn, error), and support for multiple transports (e.g., logging to files, external services).
Use a retry mechanism within your sendOtpSms function in otp.service.js to handle transient network errors between your server and Plivo. Include a delay, potentially with exponential backoff, between retry attempts.
Express-validator sanitizes and validates user inputs in the API layer. This prevents invalid data from causing issues in the service layer and enhances security by mitigating common vulnerabilities like injection attacks.