Implement Secure OTP Verification in Next.js with Plivo Verify - code-examples -

Frequently Asked Questions

To send an OTP SMS, create a Next.js API route that uses the Plivo Node.js SDK to call the Plivo Verify API's `client.verify.session.create()` method. This API route should handle the request containing the user's phone number and make the API call to Plivo. It needs to send the recipient's phone number and specify 'sms' as the channel. The API route should also return the `session_uuid` to the client for later verification.
First install the Plivo Node.js SDK (`npm install plivo`). Then, set up environment variables (`PLIVO_AUTH_ID`, `PLIVO_AUTH_TOKEN`) in `.env.local`. Create API routes in Next.js (e.g., `/api/otp/send` and `/api/otp/verify`) to handle the Plivo Verify API interaction. Initialize the Plivo client in your API routes using your environment variables to make calls to the Plivo Verify API.
The Plivo Verify API is used for sending and validating One-Time Passwords (OTPs) for various purposes like Two-Factor Authentication (2FA) and phone number verification during user signup. It supports sending OTPs via SMS, Voice, and WhatsApp.
Create an API route (e.g., `/api/otp/verify`) that receives the `session_uuid` (from sending the OTP) and the user-entered OTP. Use the Plivo SDK's `client.verify.session.validate()` method to check if the OTP is valid, matching it against the `session_uuid`. Return a success/failure response to the frontend based on Plivo's response. Ensure you check the Plivo documentation for robust validation indicators (status codes or flags).
Plivo offers several benefits for OTP verification including: a simple API, global coverage, high delivery rates for SMS messages, competitive pricing, and built-in fraud protection features (like Fraud Shield), making it a reliable choice for enhancing security.
Two API routes are typically used: `/api/otp/send` to send the OTP via the Plivo Verify API, and `/api/otp/verify` to check the user-entered OTP against the Plivo Verify API using the `session_uuid`.
Obtain your `AUTH_ID` and `AUTH_TOKEN` from the Plivo console under API Keys & Credentials. Store these values as environment variables in a `.env.local` file in your project's root directory. Next.js loads environment variables from this file for local development. Never commit `.env.local` to version control.
You will need Node.js and npm/yarn, a Plivo account (sign up at plivo.com), a basic understanding of React and Next.js components, API routes, hooks, and access to a terminal.
Rate limiting is crucial for security and to prevent abuse, such as preventing attackers from spamming phone numbers or brute-forcing OTPs. It should be implemented from the start, especially in production environments. Limit OTP requests and verification attempts based on IP, user ID, or phone number.
Implement `try...catch` blocks in both API routes and frontend code. Log detailed error messages server-side for debugging and provide user-friendly feedback in the frontend UI. You can also add retries for specific error scenarios, such as network issues during API calls to Plivo.
The article recommends using Node.js version 18 or later when setting up a Next.js project with Plivo OTP integration for optimal compatibility.
While the example uses basic regex, consider using a dedicated library like `react-phone-number-input` on the client-side and a robust server-side library (e.g., Google's `libphonenumber`) for thorough format checking, especially if handling international numbers.
The example doesn't explicitly include a resend feature, but you can implement it by adding a "Resend OTP" button to the UI. This button should call the same `/api/otp/send` API route again. Add a cooldown period to prevent abuse, typically by disabling the button for a short period after each click.
Although not shown in the article, in a real app, integrate OTP verification with your user database. Store user phone numbers (in E.164 format), and a verification flag (`is_phone_verified`). After successful OTP verification, update this flag in your database.