Frequently Asked Questions
Integrate Infobip's 2FA into your RedwoodJS app by first setting up a new Redwood project and configuring environment variables for your Infobip credentials. Then, configure the 2FA service in the Infobip portal, including creating a 2FA application and message template. Finally, implement the backend service, GraphQL API, and frontend components to handle the OTP flow within your application.
The Infobip 2FA Application ID is a unique identifier for your 2FA application within the Infobip platform. It is required when making API calls to Infobip for sending and verifying OTPs, and it should be stored securely as an environment variable in your RedwoodJS project.
RedwoodJS uses environment variables to store sensitive information like Infobip API keys and application IDs. This practice prevents these secrets from being hardcoded into your application's source code, which improves security and makes managing these credentials easier across different environments.
To send OTPs, create a RedwoodJS service that makes a POST request to the Infobip 2FA API. This service should use environment variables for your Infobip credentials and the user's phone number to send the OTP message. The response from Infobip will include a pinId
that's essential for later verification.
The pinId
is a unique identifier for a specific OTP sending request. It's returned by Infobip after you send an OTP and is crucial for the verification step. Your RedwoodJS app must store this pinId
temporarily and send it back to Infobip when verifying the user-entered OTP.
Use @requireAuth
for the sendOtp
GraphQL mutation when users need to be logged in to request an OTP, such as when adding 2FA to an existing account. If the OTP is part of a registration process where users aren't logged in yet, you might use @skipAuth
, but ensure robust rate limiting is in place to prevent abuse.
Create a RedwoodJS service that calls the Infobip verification API using the received pinId
and the OTP entered by the user. This will return a success or failure status, and the service can optionally update the user's record in the database if verification succeeds.
The E.164 format is recommended for storing phone numbers, as it's an international standard. An example of this format is +14155552671. Use a robust library like google-libphonenumber
or libphonenumber-js
for proper validation and normalization.
Implement rate limiting at multiple levels: configure limits within your Infobip 2FA application settings, leverage API gateway or platform-level rate limiting (e.g., on Vercel or Netlify), and optionally add application-level limits within your services using middleware or custom logic to prevent abuse.
Implement robust error handling in your RedwoodJS service and frontend components. Use try...catch
blocks around API calls, log errors using Redwood's logger
, and display user-friendly error messages in the frontend using Redwood's <Toaster>
component.
Yes, you can customize the message content within the Infobip Message Template, but you must keep the {{pin}} placeholder so Infobip can correctly insert the generated OTP into the message. Also, ensure any customizations comply with Infobip's guidelines and local regulations for SMS messaging.
You need Node.js, Yarn, the RedwoodJS CLI, an Infobip account, and a basic understanding of RedwoodJS, React, GraphQL, and Node.js to implement Infobip OTP.
Use a specialized library like google-libphonenumber
or its JavaScript port libphonenumber-js
for robust phone number parsing and validation on both the backend and frontend of your RedwoodJS application. This will ensure you handle various international number formats correctly and prevent common validation errors.
Input validation helps prevent malicious actors from exploiting vulnerabilities. In the context of OTP, validating phone numbers and PINs protects against invalid input, injection attacks, and other security risks.
RedwoodJS Forms provide built-in components and utilities for creating and managing forms, including input validation and error handling. This simplifies frontend development and improves the user experience.
Implement OTP/2FA Phone Verification in RedwoodJS with Infobip
Build a secure phone number verification system using Infobip's Two-Factor Authentication (2FA) API with One-Time Passwords (OTP) via SMS in your RedwoodJS application. This guide walks you through creating a complete OTP flow where users verify their phone numbers by receiving and entering a code.
Add a verification layer beyond email/password authentication – commonly used during registration or for sensitive actions.
Project Overview and Goals
Goal: Build a secure and reliable phone number verification system within a RedwoodJS application using Infobip's 2FA API for sending and verifying OTPs via SMS.
Problem Solved:
Technologies Used:
System Architecture:
The phone verification process follows these steps:
sendOtp
) containing the phone number to the RedwoodJS API backend.otp.ts
service function.verifyOtp
) containing thepinId
(received earlier) and the entered OTP to the RedwoodJS API backend.otp.ts
service function.isPhoneNumberVerified
to true).Prerequisites:
yarn global add redwoodjs
)Final Outcome: A RedwoodJS application with pages/components allowing users to:
1. Setting up the RedwoodJS Project
Create a new RedwoodJS project.
Create RedwoodJS app: Open your terminal and run:
Follow the prompts (choose TypeScript or JavaScript). This guide uses TypeScript examples where applicable, but the concepts remain the same for JavaScript.
Configure environment variables: Never hardcode Infobip credentials. Use environment variables instead. Open the
.env
file at the root of your project and add the following lines (get these values in the next step):INFOBIP_BASE_URL
: The specific base URL provided by Infobip for your account (e.g.,xxxxx.api.infobip.com
).INFOBIP_API_KEY
: Your secret API key from the Infobip portal.INFOBIP_2FA_APP_ID
: The ID of the 2FA Application you'll create in Infobip.INFOBIP_2FA_MESSAGE_ID
: The ID of the 2FA Message Template you'll create in Infobip.Important: Add
.env
to your.gitignore
file if it's not already there to prevent committing secrets. Redwood's default.gitignore
includes it.Install dependencies: Install
axios
to make HTTP requests from the backend service to Infobip:2. Configuring Infobip 2FA Service
Configure the necessary components within your Infobip account before writing code.
xxxxx.api.infobip.com
).RedwoodJS OTP App Key
)..env
file forINFOBIP_API_KEY
andINFOBIP_BASE_URL
.RedwoodJS Verification
(or similar)5
(Default, adjust as needed)true
(Recommended during testing)5m
(5 minutes, adjust as needed)1/3s
(Rate limit verification attempts)10000/1d
(Adjust based on expected traffic)5/1d
(Crucial to prevent abuse)true
.env
file forINFOBIP_2FA_APP_ID
.NUMERIC
Your verification code for Your App Name is: {{pin}}
(Customize "Your App Name" and the surrounding text for your application, but keep the{{pin}}
placeholder)6
(Commonly 4 or 6 digits)Infobip 2FA
,Verify
). This might require registration depending on the country..env
file forINFOBIP_2FA_MESSAGE_ID
.Your
.env
file should now have all four Infobip values filled in.3. Creating the Database Schema
Create a basic
User
model to associate the verified phone number with.Define the schema: Open
api/db/schema.prisma
and define a simple User model. If you already have one, addphoneNumber
andisPhoneNumberVerified
fields:phoneNumber
: Stores the user's phone number in E.164 format (e.g., +14155552671) per ITU-T Recommendation E.164 (November 2010).isPhoneNumberVerified
: Flag to track verification status.Apply migrations: Run the Prisma migrate command to create/update the database table:
Enter a name for the migration when prompted (e.g.,
addUserPhoneVerification
).4. Implementing Core Functionality (API Service)
Create a RedwoodJS service to handle communication with the Infobip API.
Generate the service:
This creates
api/src/services/otp/otp.ts
and associated test/scenario files.Implement service logic: Update
api/src/services/otp/otp.ts
with the following logic:google-libphonenumber
for production phone validation).axios
, including theAuthorization
header.sendOtp
returns thepinId
provided by Infobip. This ID links the sending request to the verification request.verifyOtp
uses thepinId
and the user-providedpin
to check with Infobip.WRONG_PIN
,PIN_NOT_FOUND
) to returnfalse
instead of throwing a server error.5. Building the API Layer (GraphQL)
Now, let's expose our service functions through the GraphQL API.
Generate the SDL (Schema Definition Language) file:
This creates
api/src/graphql/otp.sdl.ts
.Define the GraphQL Schema: Open
api/src/graphql/otp.sdl.ts
and define the mutations and types.sendOtp
andverifyOtp
.SendOtpResponse
,VerifyOtpResponse
) to provide clear feedback (success status,pinId
, and messages).@skipAuth
is used here for simplicity, assuming this might be part of a registration flow where the user isn't logged in yet. If this is for logged-in users, replace@skipAuth
with@requireAuth
and adjust the service logic to usecontext.currentUser
to associate the verification with the correct user.@skipAuth
requires careful consideration of rate limiting on the API endpoints to prevent abuse.RedwoodJS automatically maps the
sendOtp
andverifyOtp
mutations defined here to the service functions of the same name we created earlier.6. Integrating with the Frontend (Web Side)
Let's create the UI components for users to interact with the OTP flow.
Generate Pages: We need two pages: one to request the OTP and one to verify it.
VerifyOtp
page includes a route parameter{pinId}
to receive thepinId
generated by thesendOtp
step.Implement RequestOtp Page: Update the file
web/src/pages/RequestOtpPage/RequestOtpPage.tsx
.useMutation
hook to call thesendOtp
GraphQL mutation.loading
anderror
from the hook and Redwood Toast.pinId
from the response and navigates the user to theVerifyOtpPage
, passing thepinId
in the URL.Implement VerifyOtp Page: Update the file
web/src/pages/VerifyOtpPage/VerifyOtpPage.tsx
.pinId
as a prop via the route parameter.verifyOtp
mutation using the receivedpinId
and the user-enteredpin
.Update Routes: Ensure your routes in
web/src/Routes.tsx
are correctly set up:7. Adding Security Features
@skipAuth
.sendPinPerPhoneNumberLimit
,verifyPinLimit
) in the Infobip App setup. These provide a baseline./graphql
).graphql-shield
or custom logic in your services (using Redis or the database) to track request frequency per user ID, IP address, or phone number. Start with Infobip and platform limits first.zod
oryup
within the service layer for more complex rules on phone numbers or PINs if needed. RedwoodJS allows easy integration with these. Remember the importance of robust phone number validation using libraries likegoogle-libphonenumber
orlibphonenumber-js
.libphonenumber-js
for robust frontend phone number parsing and validation before even sending to the backend..env
and environment variables in deployment – never commit keys.8. Implementing Error Handling and Logging
try...catch
blocks aroundaxios
calls.logger
(api/src/lib/logger.ts
) is used to log informational messages, warnings, and errors, including details from Infobip API errors where available. This is crucial for debugging.false
return values or specific error messages, rather than generic server errors.useMutation
hook providesloading
anderror
states, used to give feedback to the user (disable buttons, show error messages).<Toaster>
component is used to display non-blocking success or error notifications.This setup provides a solid foundation for integrating Infobip OTP into your RedwoodJS application. Remember to adapt the database interactions, authentication context (
@requireAuth
vs@skipAuth
), and validation logic to your specific application requirements.Frequently Asked Questions (FAQ)
How do I implement OTP verification in RedwoodJS?
Implement OTP verification in RedwoodJS by creating a service that communicates with an SMS provider (like Infobip 2FA API), exposing GraphQL mutations for sending and verifying OTPs, and building React components for user interaction. Store phone numbers in E.164 format and use Prisma to track verification status in your database.
What is Infobip 2FA and how does it work?
Infobip 2FA is a dedicated two-factor authentication service that manages the complete OTP lifecycle. It generates time-limited PINs, sends them via SMS to users' phones, and verifies user-submitted codes. Configure rate limits and PIN settings in the Infobip portal to prevent abuse while maintaining security.
How do I format phone numbers for SMS verification?
Store and validate phone numbers in E.164 format (e.g., +14155552671) per ITU-T Recommendation E.164 (November 2010). Use
libphonenumber-js
for production-grade validation that handles international formats correctly. E.164 ensures consistent formatting across all carriers and countries.Should I use @skipAuth or @requireAuth for OTP endpoints?
Use
@skipAuth
for registration flows where users aren't logged in yet, but implement strict rate limiting to prevent abuse. Use@requireAuth
when adding phone verification to existing user accounts. With@requireAuth
, accesscontext.currentUser
in your service to update the correct user's verification status.How do I prevent OTP SMS spam and abuse?
Implement multi-layer rate limiting: (1) Configure Infobip limits in your 2FA Application (e.g., 5 SMS per phone number per day), (2) Enable platform-level rate limiting on your GraphQL endpoint, and (3) Consider Redis-based application-level tracking for granular control. Never use
@skipAuth
without rate limiting.What Node.js version should I use for RedwoodJS?
Use Node.js v20 LTS "Iron" or v22 LTS "Jod" for production RedwoodJS applications as of October 2025. These versions receive long-term support with security updates. RedwoodJS also supports v24 Current. Avoid odd-numbered versions which have shorter support cycles.
How do I handle Infobip OTP errors in RedwoodJS?
Catch specific Infobip error codes (
PIN_NOT_FOUND
,WRONG_PIN
) and returnfalse
for verification failures rather than throwing server errors. Log detailed error information server-side using RedwoodJS's built-in logger for debugging, but provide generic user-facing error messages to prevent information disclosure.Can I use Infobip OTP with RedwoodJS authentication?
Yes. Integrate OTP verification with RedwoodJS auth by calling your verification service within authenticated contexts. After successful OTP verification, update the user's
isPhoneNumberVerified
field in your database using Prisma. Access the current user viacontext.currentUser
in your service functions.How long does an Infobip OTP code remain valid?
Configure PIN Time To Live (TTL) in your Infobip 2FA Application settings. Common values are 5 minutes (5m) or 10 minutes (10m). Balance security (shorter TTL) with user experience (longer TTL for users in poor network conditions). Infobip automatically expires codes after the configured TTL.