Frequently Asked Questions
To set up MessageBird OTP in Node.js, you'll need to install necessary dependencies like Express, the MessageBird SDK, Handlebars, dotenv, and body-parser. Create the project structure, set up your .env file with your MessageBird API key, and then implement the core logic within index.js and your Handlebars view templates as described in the guide. This allows for user interaction to send and verify the OTP codes via SMS through the MessageBird API and an Express server.
The MessageBird Verify API is used for generating and sending One-Time Passwords (OTPs) via SMS, commonly for Two-Factor Authentication (2FA). It allows you to securely verify a user's phone number by sending a unique code and then verifying it, enhancing your app's security by adding a second verification factor beyond a password.
MessageBird OTP requires a live API key because it involves sending real SMS messages to users' phones, which incurs costs. Test API keys don't have access to the SMS functionality needed for the Verify API. You can find your live API key in the "Developers" section, "API access" tab, within your MessageBird Dashboard. Create one if you haven't already.
Two-Factor Authentication with MessageBird is beneficial when you want to strengthen the security of your applications, especially during sensitive actions like login, account updates, or financial transactions. Adding 2FA helps protect against unauthorized access, even if a user's password is compromised.
You can send OTPs with the MessageBird API by making a POST request to /send-otp route with the user's phone number in international format. Ensure your backend is set up with the MessageBird Node.js SDK and uses messagebird.verify.create() with the user's number and message template containing %token placeholder. A unique verification ID is generated and returned in the API's response which is then used to verify the entered OTP.
Prerequisites for MessageBird OTP integration include installed Node.js and npm (or yarn), a MessageBird account with a live API key, a phone number capable of receiving SMS for testing, and basic understanding of Node.js, Express.js, and asynchronous JavaScript.
The MessageBird OTP system uses a three-part architecture involving the user's browser, your Node.js/Express server, and the MessageBird Verify API. The browser interacts with the server for phone number and OTP submission, the server handles requests and interacts with the API using the SDK, and the MessageBird API generates, sends, and verifies the OTP.
Implement error handling by checking for errors returned by the messagebird.verify.create and messagebird.verify.verify functions. Use console.error for logging detailed errors, then provide helpful messages to the user on the UI based on the error codes. This tutorial demonstrates handling errors for invalid numbers, API issues, and incorrect OTPs, improving user experience.
Enhance OTP security by using environment variables for API keys, implementing robust phone number and token validation, adding rate limiting to the /send-otp route (and potentially /verify-otp), always using HTTPS in production, and implementing secure session management.
To verify the OTP, the user enters the code they received via SMS. The backend takes this user-entered token along with the verification ID (generated when sending the initial request) and calls the messagebird.verify.verify(id, token, callback) function. If successful, the callback renders a success page, and the user's phone number is marked as verified.
Yes, you can customize the MessageBird OTP message by providing a custom template with the template parameter in messagebird.verify.create(). The %token placeholder within the template is replaced with the actual OTP, allowing flexibility in wording and branding.
You can test your integration by running the application locally with node index.js and manually interacting with it in your browser. You should be able to submit your phone number, receive an OTP via SMS, and then submit the OTP for verification. Alternatively, test with curl by sending POST requests to /send-otp and /verify-otp endpoints with appropriate parameters.
Check for common issues such as incorrect or test API keys, phone numbers not in E.164 format, originator restrictions, expired or invalid tokens, message delivery issues, and rate limits. Ensure your MessageBird account has a sufficient balance for sending messages. Review the troubleshooting section of the article.
Deployment considerations include managing environment variables securely, enforcing HTTPS, utilizing a process manager like PM2, configuring a production-ready logging solution, and ensuring all production dependencies are properly installed.
To integrate with user accounts, after successful verification, store a flag (e.g., isPhoneNumberVerified: true) in your user database. Ideally, the verificationId should also be stored in a server-side session during the process for enhanced security if tied to a logged-in user, rather than relying on hidden form fields.
MessageBird OTP/2FA Tutorial: Node.js + Express Implementation Guide
Build a secure One-Time Password (OTP) verification system for Two-Factor Authentication (2FA) using Node.js, Express, and the MessageBird Verify API. This step-by-step guide covers everything from project setup to deployment.
By the end of this tutorial, you'll have a functional web application that:
You'll add a second verification factor beyond passwords, confirming users possess their registered phone number.
Important Security Context: SMS-based OTP is more vulnerable to interception than Time-based One-Time Password (TOTP) authenticator apps (per OWASP Multifactor Authentication guidelines). SMS OTP is susceptible to SIM swapping attacks (where attackers hijack your phone number by convincing carriers to transfer it to a new SIM card), SS7 protocol exploits (network-level attacks that intercept SMS messages), and man-in-the-middle attacks (where attackers intercept SMS messages in transit). For high-security applications, implement TOTP as your primary 2FA method with SMS OTP as a fallback or account recovery option.
Compliance Requirements: When implementing SMS OTP, consider these requirements:
Technologies You'll Use:
Prerequisites:
Cost Estimates by Region:
System Architecture:
The flow involves three main components:
Request Flow:
1. Set Up Your Node.js Project Environment
Create your project directory and install the necessary dependencies.
Create Project Directory: Open your terminal and create a new directory for the project:
Initialize Node.js Project: Initialize the project using npm (the
-yflag accepts default settings):Install Dependencies: Install Express, MessageBird SDK, Handlebars, dotenv, and body-parser:
Optional but Recommended: For robust phone number validation, install
libphonenumber-js:Example package.json:
Create Project Structure: Set up your directory structure:
Your structure should look like this:
Configure Environment Variables: Never hardcode your MessageBird API key. Use
dotenvto load it from a.envfile.Get Your MessageBird Live API Key:
Add the Key to
.env: Open.envand add:Replace
YOUR_LIVE_API_KEYwith your actual key.Add a Template to
.env.example: Create an example file without exposing secrets:Create
.gitignore: Add.envto your.gitignorefile to prevent committing secrets:2. Build the Express Application with MessageBird Integration
Build the Express application logic in
index.jsand create the corresponding Handlebars views.Set Up
index.js: Openindex.jsand add the initial setup:dotenv.config()first? Load environment variables early before using them in the MessageBird SDK initialization.bodyParser? Parse form data (application/x-www-form-urlencoded) and make it available inreq.body.express-handlebars? Dynamically generate HTML pages with templates, separating presentation from logic.Version Compatibility: If you're using
express-handlebarsv5 or earlier, useexphbs({ defaultLayout: 'main' })instead ofexphbs.engine({ defaultLayout: 'main' }). Check your installed version withnpm list express-handlebars.Create Main Layout (
views/layouts/main.handlebars): Define the basic HTML structure shared by all pages:Accessibility improvements: Added
lang="en"attribute,role="main"for screen readers, and improved color contrast for error/success messages.Step 1: Request Phone Number (
views/step1.handlebars) Display the form for users to enter their phone number:{{#if error}}: Conditionally displays an error message if theerrorvariable is passed to the template.action="/send-otp": Form data is sent via HTTP POST to the/send-otproute.type="tel": Mobile browsers display a numeric keypad.role="alert",aria-live="polite",aria-required="true", andaria-describedbyfor screen readers.Add Route for Step 1 (GET
/) Add this route toindex.jsbefore theapp.listen()call:Step 2: Send OTP and Request Code (
views/step2.handlebars) Ask the user to enter the OTP they received. Include a hidden field to pass the MessageBird verification ID.input type="hidden" name="id": Stores the verification ID from MessageBird. The server needs it to link the token back to the original request, but users don't need to see it.pattern="\d{6}": Basic HTML5 validation for a 6-digit number.Add Route for Sending OTP (POST
/send-otp) Handle phone number submission, call the MessageBird API to send the OTP, and render the code entry form. Add this toindex.js:libphonenumber-jsin production for accurate E.164 validation.messagebird.verify.create(number, params, callback): Core API call.number: Recipient's phone number in E.164 format (e.g., +14155552671)params: Configuration optionsoriginator: Sender ID displayed on user's phone. Must be alphanumeric (max 11 chars) or verified MessageBird number. Important: Alphanumeric originators work in Europe but not in US/Canada. For North America, use a purchased MessageBird virtual number or shortcode.template: Message text.%tokenis replaced by the OTP.timeout: Token validity in seconds. Default: 600 seconds (10 minutes), not 30 seconds. Adjust for your use case.tokenLength: OTP length. Default: 6 digits.callback(err, response): Handles async responseerr: Error occurred (invalid number, API key issue, insufficient balance). Log detailed error and show user-friendly message.response: Request successful.response.idis the unique identifier for this verification attempt.Production validation example with libphonenumber-js:
MessageBird API Error Codes:
Step 3: Verification Result (
views/step3.handlebars) Show success message upon correct verification:Integration Example: In production, mark the phone number as verified in your database:
Add Route for Verifying OTP (POST
/verify-otp) Take the verification ID and user-entered token, call MessageBird to verify them, and render success or failure. Add this toindex.js:messagebird.verify.verify(id, token, callback): Key API callid: Verification ID from thecreatecall (passed via hidden form field)token: OTP entered by usercallback(err, response):err: Token was incorrect, expired, or ID was invalid. Renderstep2with error message, passidback so user can retry.response: Token correct! Render success page. In production, mark the user's phone number as verified in your database.3. Implement Error Handling and Logging Best Practices
Implement robust error handling and logging:
messagebird.verify.createandmessagebird.verify.verify. Log detailed errors to console (console.error) for debugging. Display user-friendly messages on the appropriate page. Check specific error codes (21 for invalid recipient, 23 for invalid token) to provide better feedback./send-otp.console.logandconsole.error. For production, use a dedicated logging library (Winston or Pino) to structure logs, write to files, and set log levels.Winston configuration example:
Error Monitoring: Integrate error monitoring services for production:
4. Security Best Practices for OTP Implementation
Protect your application and users:
API Key Security: Load API key from
.envand never commit to version control. Ensure.envis in.gitignore. In production, use your platform's secure environment variable management.Input Validation: Sanitize and validate all user inputs. Use
libphonenumber-js(lighter than Google's libphonenumber) for robust E.164 format checking. Validate token format (numeric, expected length).Rate Limiting: Protect
/send-otpfrom abuse. Repeated code requests cost money and harass users. Implement rate limiting per IP or user account withexpress-rate-limit. MessageBird limits 3 verification attempts per ID (maxAttempts: 3), but add application-level rate limiting. Consider stricter limits on/verify-otpto prevent token guessing attacks.Install rate limiting:
Configure rate limiting:
Per-phone-number rate limiting example:
HTTPS: Always use HTTPS in production to encrypt client-server communication.
Session Management: For real applications with user accounts_ use secure session management. Don't rely solely on hidden form fields for sensitive state like verification IDs. Store server-side in user's session.
Secure session storage options:
CSRF Protection: Implement CSRF protection to prevent cross-site request forgery attacks:
Recovery Codes: Provide users with recovery codes (single-use backup codes) for production 2FA in case they lose phone access. Store hashed in your database.
5. Test Your OTP Application
Verify everything works correctly:
Start the Application: Ensure
.envhas the correctMESSAGEBIRD_API_KEY. Run from your terminal:You should see
Server listening on http://localhost:3000.Manual Browser Testing:
http://localhost:3000in your browser.+1XXXYYYZZZZ). Click "Send Code."Automated Testing: Implement unit and integration tests with Jest:
Example test (test/otp.test.js):
Mock Testing (without SMS credits): Use MessageBird's test mode or mock the SDK:
API Endpoint Testing (Optional – using
curl): Test POST endpoints directly.Send OTP:
Look for HTML response with Step 2 form and hidden
idfield. Extract theidvalue.Verify OTP:
Look for HTML response for Step 3 (success) or Step 2 (failure).
6. Enhance Your Implementation
Improve security and user experience:
Integrate with User Accounts: Store verification status (
isPhoneNumberVerified: true) in your database upon success.Database schema example (PostgreSQL):
Session Management: Store
verificationIdserver-side in session instead of hidden field for better security with logged-in users.Voice (TTS) OTP: Set
params.typeto'tts'inmessagebird.verify.createto send OTP via voice call instead of SMS.Customization: Explore
verify.createparameters:timeout(default 600s = 10 minutes),tokenLength(default 6),language, andvoice(for TTS).UI/UX: Improve interface and provide clearer feedback.
Resend Code: Allow users to request codes again after a delay.
TOTP Implementation: Implement TOTP (Time-based One-Time Password) with authenticator apps as primary 2FA, using SMS as fallback for higher security.
7. Troubleshoot Common Issues
Solve common problems:
MESSAGEBIRD_API_KEYin.envis correct and is a Live key. Check for typos or spaces. Error messages mention authentication failure.+14155552671). Include '+' and country code. API error code 21 indicates this. Uselibphonenumber-jsfor production validation.timeoutduration (default 600 seconds = 10 minutes, not 30 seconds). Verification fails if users take too long (error code 20 or 23). Ensure entered token matches received code. MessageBird allows up to 3 attempts per ID (maxAttempts: 3).Diagnostic Checklist:
MESSAGEBIRD_API_KEYis set correctly in.env8. Deploy to Production
Prepare your application for deployment:
Environment Variables: Never hardcode API keys. Use your platform's environment variable management (Heroku Config Vars, AWS Secrets Manager, Docker environment variables). Don't deploy
.envfiles.Platform-specific guides:
heroku config:set MESSAGEBIRD_API_KEY=your_keydocker run -e MESSAGEBIRD_API_KEY=your_keyor docker-composeHTTPS: Configure HTTPS using Nginx or your platform's load balancer.
Process Management: Use PM2 or Nodemon (development) to keep your application running reliably and handle restarts.
Logging: Configure robust logging for production monitoring.
Dependencies: List all production dependencies in
package.json(notdevDependencies). Runnpm install --productionin deployment environment.Docker deployment example:
Frequently Asked Questions About MessageBird OTP/2FA
How do I implement OTP verification in Node.js?
Implement OTP verification in Node.js using the MessageBird Verify API. Install the
messagebirdSDK, initialize the client with your API key, create a verification request withclient.verify.create(), and verify user input withclient.verify.verify(). The process includes sending an SMS with a random token and validating the user's response within the timeout period (default 600 seconds).What is MessageBird Verify API?
MessageBird Verify API is a service that handles OTP (One-Time Password) generation, delivery, and verification for two-factor authentication. It automatically generates random tokens, sends them via SMS, manages token expiration, and provides verification endpoints. The API handles rate limiting, attempt tracking, and security features to protect against brute-force attacks.
Is SMS OTP secure for 2FA?
SMS OTP provides moderate security for two-factor authentication but has known vulnerabilities. According to OWASP Multifactor Authentication guidelines, SMS is susceptible to SIM swapping attacks, SS7 protocol exploits, and device theft. For high-security applications, use TOTP (Time-based One-Time Password) apps like Google Authenticator or hardware tokens. SMS OTP works best for low-to-medium security scenarios when combined with rate limiting and account monitoring.
Mitigation strategies:
How much does MessageBird SMS cost?
MessageBird SMS pricing varies by destination country. As of 2024, US SMS costs approximately $0.008 per message. International rates differ significantly – check MessageBird's pricing page for your target regions. The Verify API uses standard SMS pricing with no additional verification fees. Calculate costs based on your expected verification volume and user geography.
What's the difference between SMS OTP and TOTP?
SMS OTP delivers codes via text message to your phone number, while TOTP (Time-based One-Time Password) generates codes locally using an authenticator app. TOTP is more secure because it doesn't rely on telecom networks vulnerable to interception. SMS OTP offers better user experience since it requires no app installation. Use TOTP for high-security applications and SMS OTP for user convenience in lower-risk scenarios.
How do I handle MessageBird API errors in Node.js?
Handle MessageBird API errors using try-catch blocks around API calls. Check for specific error codes in the response: error code 2 indicates permission issues, code 9 means missing parameters, code 20 indicates an invalid verification ID, code 21 means the recipient number is invalid, code 23 indicates an invalid token, and code 25 indicates too many attempts. Always provide user-friendly error messages and implement logging for debugging. Use proper HTTP status codes (400 for validation errors, 500 for server errors, 429 for rate limiting).
Can I customize the OTP message template in MessageBird?
Yes, customize the OTP message template using the
templateparameter inclient.verify.create(). Include%tokenas a placeholder where the OTP code appears. Keep messages under 160 characters to avoid SMS concatenation. Example:"Your VerifyApp code is %token. Valid for 10 minutes."Alphanumeric sender IDs work in Europe but not in the US or Canada, where you need a registered long code.How long should OTP codes remain valid?
Set OTP validity between 5–10 minutes (300–600 seconds) using the
timeoutparameter. MessageBird's default is 600 seconds (10 minutes). Shorter timeouts improve security but may frustrate users with delayed messages. Longer timeouts reduce user friction but increase vulnerability to replay attacks. Consider your user experience needs and security requirements when setting this value.How do I implement rate limiting for OTP requests?
Implement rate limiting using
express-rate-limitmiddleware. Limit OTP generation to 3–5 requests per hour per IP address and per phone number. Set verification attempt limits to 3 tries per verification ID (MessageBird's default). Store rate limit data in Redis for distributed systems or use in-memory storage for single-server deployments. Return HTTP 429 (Too Many Requests) when limits are exceeded.What happens if a user doesn't receive the OTP SMS?
If a user doesn't receive the OTP SMS, check MessageBird's delivery status using the verification ID. Common causes include invalid phone numbers, carrier filtering, or network delays. Implement a "resend code" feature with rate limiting (maximum 2–3 resends per verification attempt). Provide alternative verification methods like voice calls or email as fallbacks. Log delivery failures for monitoring and troubleshooting.
9. Complete Code Repository
A complete, runnable version of this project is available on GitHub at github.com/your-username/messagebird-node-otp-example.
You now have a functional Node.js application for SMS OTP verification using MessageBird's Verify API. This provides a solid foundation for adding two-factor authentication to your web applications. Adapt the error handling, security measures, and UI/UX to fit your production environment's specific needs.