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 `` 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.
Implementing Infobip OTP/2FA in RedwoodJS
This guide provides a step-by-step walkthrough for integrating Infobip's Two-Factor Authentication (2FA) service using One-Time Passwords (OTP) via SMS into a RedwoodJS application. We'll build a system where users can verify their phone numbers by receiving an OTP from Infobip and entering it into our application.
This approach enhances security by adding a verification layer beyond just email/password, commonly used during registration or for sensitive actions.
Project Overview and Goals
Goal: To 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
Let's start by creating a new RedwoodJS project.
Create the RedwoodJS App: Open your terminal and run:
Follow the prompts (choose TypeScript or JavaScript). This guide will use TypeScript examples where applicable, but the concepts are the same for JavaScript.
Environment Variables: Infobip credentials should never be hardcoded. We'll use environment variables. Open the
.env
file at the root of your project and add the following lines (we'll 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
usually includes it.Install Dependencies: We need a way to make HTTP requests from our backend service to Infobip. Let's use
axios
.2. Configuring Infobip 2FA Service
Before writing code, we need to configure the necessary components within your Infobip account.
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 ensure you 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
.Now your
.env
file should have all four Infobip values filled in.3. Creating the Database Schema
We need a basic
User
model to potentially 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, you might addphoneNumber
andisPhoneNumberVerified
fields.phoneNumber
: Stores the user's phone number (consider storing in E.164 format, e.g., +14155552671).isPhoneNumberVerified
: A 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)
We'll create a RedwoodJS service to handle the 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 the file
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.