Frequently Asked Questions
Implement rate limiting with a library like express-rate-limit to prevent abuse of your /send-sms endpoint, control costs, and enhance the stability of your service.
Use the Vonage Messages API and Node.js SDK. Set up an Express server, define an endpoint that accepts recipient number and message, then utilize the SDK to send the SMS via the API. This setup allows for sending messages programmatically.
The Vonage Messages API enables sending SMS messages programmatically from within applications. It handles the complexities of carrier integration so developers can easily add SMS functionality to projects like notifications or 2FA.
The private key, along with your Application ID, authenticates your application with the Vonage Messages API. It's crucial for security and should never be exposed publicly or committed to version control. Keep it safe and secure.
Whitelisting is mandatory for trial Vonage accounts. Add and verify the recipient number via the Vonage dashboard before sending test messages. This step is crucial to avoid "Non-Whitelisted Destination" errors.
Yes, Vonage provides a Node.js SDK (@vonage/server-sdk) that simplifies interaction with both the Messages API (recommended) and the older SMS API. Ensure you are using the correct API and corresponding SDK methods, and check for any version compatibility.
Create a Vonage application, enable the Messages capability, generate and securely store your private key, link a Vonage virtual number, and configure these credentials as environment variables in your Express project. Use the @vonage/server-sdk to interact with the API.
The dotenv module loads environment variables from a .env file into process.env, making it easy to manage configuration like API keys, secrets, and other settings without hardcoding them in your application code.
Vonage has two SMS APIs. Setting the Default SMS API to "Messages API" in the Vonage dashboard ensures that the SDK uses the correct API, avoiding potential conflicts or unexpected behavior, especially with webhooks.
Implement try...catch blocks around the vonage.messages.send() call. Log error details, including any specific Vonage error information from the API response, to assist with debugging. Consider using a logging library for structured logs.
E.164 is an international telephone number format that includes the country code and number without any symbols or formatting (e.g., +15551234567 becomes 15551234567). It ensures consistent and accurate number handling for SMS delivery.
Never commit .env or private key files to version control. Use platform-specific environment variable management in production. Consider storing the private key content as an environment variable directly for platforms like Heroku.
Use a platform like Heroku, AWS, or Google Cloud. Configure environment variables securely. Employ build processes if necessary, use a Procfile if required by the platform, and ensure all dependencies are installed correctly.
Double-check your Application ID, private key path, and the key file's content for accuracy. Verify correct file permissions. Ensure the Default SMS Setting in the Vonage dashboard is set to 'Messages API'.
MessageBird with Next.js and Supabase: OTP-Based Two-Factor Authentication
Introduction
Two-factor authentication (2FA) using One-Time Passwords (OTPs) adds an essential security layer to web applications by requiring users to verify their identity through a second factor – typically a verification code sent to their mobile device via SMS. This comprehensive guide demonstrates how to implement SMS-based OTP two-factor authentication in a Next.js application using MessageBird for reliable SMS delivery and Supabase for authentication and database storage.
What You'll Learn:
Prerequisites:
Project Overview
Architecture Flow:
Technologies:
1. Setting Up Your Next.js OTP Authentication Project
Initialize Next.js Project
Install Dependencies
Package Purposes:
messagebird: Official MessageBird Node.js client for SMS API (npm)@supabase/supabase-js: Supabase JavaScript client@supabase/ssr: Server-side rendering authentication helpers for Next.jsConfigure Environment Variables
Create
.env.localin project root:Get your credentials:
.env.localto version controlUpdate
.gitignoreEnsure your
.gitignoreincludes:2. Supabase Database Setup for OTP Storage
Create OTP Storage Table
Execute this SQL in Supabase SQL Editor:
Security Considerations:
3. MessageBird SMS API Configuration
Initialize MessageBird Client
Create
lib/messagebird.ts:Important Notes:
4. Supabase Client Configuration for Next.js
Create
lib/supabase.ts:5. Secure OTP Generation and Validation Logic
Create
lib/otp.ts:Security Best Practices:
crypto.randomInt()_ notMath.random()(predictable)6. Next.js API Route: Send OTP via SMS
Create
app/api/send-otp/route.ts:7. Next.js API Route: Verify OTP Code
Create
app/api/verify-otp/route.ts:8. React Frontend Components for OTP Authentication
OTP Request Form
Create
components/OTPRequestForm.tsx:OTP Verification Form
Create
components/OTPVerifyForm.tsx:Main Page
Create
app/page.tsx:9. Testing Your OTP Two-Factor Authentication
Development Server
Navigate to
http://localhost:3000Test Flow
Request OTP:
+15551234567Verify OTP:
Common Test Cases
Testing with MessageBird Trial
10. SMS OTP Security Best Practices and Vulnerabilities
Critical Security Measures Implemented
Crypto-Secure OTP Generation
crypto.randomInt()instead ofMath.random()Timing Attack Prevention
secureCompare()Brute Force Protection
Rate Limiting
OTP Expiration
OTP Reuse Prevention
verifiedflag prevents code reuseDatabase Security
Environment Variable Security
.env.local(never committed)Additional Recommendations
HTTPS Only in Production
Audit Logging
Input Sanitization
SMS Message Security
Sources for Security Practices
11. Error Handling for MessageBird and Supabase
MessageBird Error Codes
MESSAGEBIRD_ACCESS_KEYin.env.localMessageBird API Error Reference
Supabase Error Handling
12. Deploying OTP Authentication to Production
Recommended Deployment: Vercel
Vercel is the recommended platform for Next.js applications with automatic optimizations.
Install Vercel CLI:
Deploy:
Configure Environment Variables:
.env.localSUPABASE_SERVICE_ROLE_KEYis only accessible server-sideProduction Considerations:
Alternative Platforms
Environment Variable Configuration
Ensure all required variables are set in production:
Post-Deployment Checklist
13. Troubleshooting Common OTP Issues
SMS OTP Not Received
Possible Causes:
Solutions:
+[country code][number]"Invalid Access Key" Error
Cause: MessageBird access key incorrect or not set
Solution:
MESSAGEBIRD_ACCESS_KEYin.env.localmatches.env.localSupabase Connection Errors
Possible Causes:
Solutions:
supabaseAdmin(service role) in API routesRate Limit Not Working
Cause: In-memory rate limiting doesn't work across serverless instances
Solution (Production):
Use Redis for distributed rate limiting:
OTP Expiration Not Working
Cause: Database timezone mismatch
Solution:
TIMESTAMP WITH TIME ZONE)new Date(expires_at) < new Date()14. Advanced OTP Features and Enhancements
Recommended Improvements
Email OTP Alternative
Resend OTP Functionality
Multi-Language Support
OTP Analytics Dashboard
Backup Authentication Methods
Advanced Rate Limiting
Improved UX
Web OTP API (Browser Autofill)
Modern browsers support auto-filling OTP from SMS:
SMS message must include:
@yourdomain.com #123456Web OTP API Documentation
15. MessageBird and Supabase Resources
Official Documentation
Security Resources
Community and Support
Conclusion
You now have a complete, production-ready implementation of SMS-based OTP two-factor authentication using MessageBird for reliable SMS delivery, Next.js for the application framework, and Supabase for authentication and secure data storage.
Key Takeaways:
Remember:
This implementation provides a solid foundation for adding 2FA to any Next.js application. Customize the UI, add additional security layers, and extend functionality as needed for your specific use case.