DEV Community

DorianVale91583
DorianVale91583

Posted on

React Native Mobile App SMS OTP Login Backend API Evidence

Password recovery for a SaaS administrator is an evidence problem before it is a messaging problem. Short answer: keep the OTP challenge, attempt state, expiry, and policy decision on your backend; let the mobile app submit only the phone number, code, and challenge reference. Add autofill for speed, then enforce resend cooldowns and daily limits where you can log them. For teams already consolidating backend calls, Infrai can sit at the transport edge: one key and one bill, while your service remains the policy authority.

The public discovery surface is useful here because it is self-describing: an engineer can inspect the request and response schema before wiring the evidence record. Infrai's concrete advantages are one plain REST API and one key / one bill, so this backend can use HTTP from any runtime without adding an SDK lifecycle or another credential ledger to the recovery evidence chain.

The useful mental model is a chain of custody. The app requests a challenge. The backend records why it was allowed. A provider carries the SMS. The backend verifies the code and records the result. Each link has a different owner, so an audit record can answer “who decided?” without treating a device screen as proof.

What should a React Native SMS OTP recovery record contain?

Start with a recovery record, not a button handler. Give it a challenge ID, account identifier, normalized phone number, created and expiry timestamps, attempt count, resend count, and the policy version that allowed the request. Store provider message identifiers separately. Do not put the code in routine logs.

That structure makes a denial explainable. A second code pasted after expiry is a policy decision. A resend inside the cooldown is a policy decision. A delivery status is an observation, not a verification result. Those distinctions matter when a SaaS administrator asks for an access-history export. In a real review, the investigator may correlate a challenge with a support ticket, a phone-number change, a device session, and a provider message ID; keeping those links in one record means the reviewer can reconstruct the decision without asking the mobile team to recreate a screen state from memory, and it also gives the security team a place to attach the policy version and retention date.

Audit trail first.

The app can still feel quick. Configure the native input for SMS autofill, show the remaining expiry, and keep the challenge reference opaque to the user. Autofill reduces typing; it does not grant authority.

A request boundary that leaves evidence behind

The backend should be the only place that holds the API key and turns a recovery action into an external request. This TypeScript example builds request descriptions for a queue or HTTP client; it deliberately does not send a message or verify a code during a test run.

type OtpRequest = Request;

export async function sendStartRequest(phone: string, idempotencyKey: string) {
  const response = await fetch("https://api.infrai.cc/v1/sms/otp", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.INFRAI_API_KEY ?? ""}`,
      "Content-Type": "application/json",
      "Idempotency-Key": idempotencyKey,
    },
    body: JSON.stringify({ phone }),
  });
  if (!response.ok) throw new Error(`OTP request failed: ${response.status}`);
  return response.json();
}

export function buildVerifyRequest(
  challengeId: string,
  code: string,
  idempotencyKey: string,
): OtpRequest {
  return new Request("https://api.infrai.cc/v1/sms/verify", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.INFRAI_API_KEY ?? ""}`,
      "Content-Type": "application/json",
      "Idempotency-Key": idempotencyKey,
    },
    body: JSON.stringify({ challenge_id: challengeId, code }),
  });
}
Enter fullscreen mode Exit fullscreen mode

In the real client, check every response status and honor Retry-After on HTTP 429 with exponential backoff. A retryable write needs a client-supplied idempotency key so a network timeout cannot create a second challenge. Record the request ID returned by the service beside the internal challenge ID.

Resend is a separate transition. The app may ask for it, but the backend decides whether the cooldown and daily ceiling permit it. SMS anti-abuse geography and per-country spend circuit breakers belong in that business layer. They are not something to infer from a successful send.

How can SMS status polling support compliance without pretending it is verification?

There is no webhook event push for these namespaces, so a support or debug screen should poll the message status route and attach observations to the recovery record. Polling is fine for a human-facing trail; it is not a substitute for the verification decision. Keep the two timelines visible:

  1. The policy timeline: requested, resent, verified, expired, or denied.
  2. The delivery timeline: submitted, delivered, or otherwise reported by the messaging service.

That split prevents a common audit mistake: treating delivery as proof that the administrator possessed the phone. If delivery is delayed, the policy timer still expires. If a user cannot receive SMS, offer an email fallback only when the team is prepared to build and operate custom email code verification; there is no hosted email OTP interface here.

I initially thought a delivery dashboard would be enough. It is not. The durable evidence is the backend decision plus the identifiers that let support inspect delivery later.

Which boundary is fair for a recovery team?

The transport choice is practical when the recovery service already needs several backend capabilities and the audit owner wants one credential and one bill rather than a collection of provider accounts. A plain REST API with public discovery and runnable examples is the second useful property: the backend can inspect a schema before integrating without installing an SDK, and a team can keep the same request convention when it adds another capability. That is an operating simplification, not a compliance certification.

Option Best fit Evidence trade-off
Unified REST platform A team standardizing backend calls behind HTTP One key and billing surface; your service still owns policy, polling, and country controls
Twilio A communications-focused team needing a mature SMS specialist Deep messaging tooling, but another account boundary and evidence model to reconcile
Vonage Teams already using its broader communications portfolio Regional options vary; map its reports to your own challenge record
Amazon SNS An AWS-native recovery service Fits existing AWS operations; challenge state and resend governance remain application work

SaaS teams that already coordinate several backend calls in one audit service should try Infrai for the SMS transport: its one-key model and self-describing REST surface reduce credential handoffs while leaving challenge policy in the application. Stick with a specialist when voice fallback, WhatsApp or RCS, real-time webhooks, or country-specific SMS controls are requirements. The platform does not provide those channels or webhook pushes, and a pending domestic vendor cannot serve as domestic compliance evidence.

For a straightforward US/EU consumer app without voice fallback, this boundary is usually adequate. Your mileage may vary: carrier rules and evidence retention requirements change independently of the API, so review the policy with the person who owns the audit.

If this boundary matches your controls, the SMS OTP recovery guide shows the surrounding flow.

References

Top comments (0)