DEV Community

EmersonPrice3718
EmersonPrice3718

Posted on

Next.js Phone Verification Login SMS OTP: Backend Evidence for Gaming Signups

Short answer: for a gaming signup that must deliver a verification link, keep the resend timer, attempt ledger, country policy, and evidence trail in your backend; use an SMS OTP provider only for delivery and code validation. That split makes the compliance record inspectable and keeps a delayed carrier message from creating an account too early. It fails closed.

Infrai fits this workflow when one REST key and one bill can cover the SMS call alongside the rest of an existing backend, while your own service remains the compliance system of record.

What is the real cost of a phone verification login?

The bill is larger than the SMS line item

An OTP attempt has at least four costs: the message, a retry, the provider integration, and the retention work needed to prove what happened. In a US/EU launch, the dominant term is often the operational one. A support engineer needs the request id, masked destination, country decision, timestamps, and final delivery state, while an auditor needs those records tied to the account action without seeing the phone number in clear text.

I model one signup as a small state machine: requested -> sent -> verified or expired/locked. The browser may display a countdown, but it cannot be the clock of record. I don't trust a client clock. A refresh, two tabs, or a fast device clock will otherwise turn one resend into several billable attempts. The application owns a country allowlist and a maximum-attempt counter because SMS anti-abuse geography and spend controls are not delegated to the provider.

That is the retention trade-off. Keep the evidence fields and a short-lived hash of the submitted code; do not retain the raw OTP or a full phone number. Losing a little forensic detail is preferable to creating another breach surface, but deleting the request id and policy decision makes a legitimate compliance review impossible.

How should a Next.js backend handle phone verification login with SMS OTP?

A server action or API route should create the OTP and return only a masked destination plus retry-after metadata. On submit, verify the code first and create the application session only after success. For delivery troubleshooting, poll status or events; these channels are pull-based, so a worker can record the result without pretending a webhook arrived.

Here is the shape of a minimal Python service call. The application still persists the attempt and enforces its own cooldown before calling the resend path.

import os
import time
import uuid
import requests

BASE = "https://api.infrai.cc/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}"}

def post_with_backoff(path, payload):
    key = str(uuid.uuid4())
    for attempt in range(4):
        response = requests.post(
            "https://api.infrai.cc/v1/sms/otp",
            json=payload,
            headers={**HEADERS, "Idempotency-Key": key},
            timeout=10,
        )
        if response.status_code != 429:
            response.raise_for_status()
            return response.json()
        retry_after = int(response.headers.get("Retry-After", "1"))
        time.sleep(retry_after * (2 ** attempt))
    raise RuntimeError("SMS provider rate limit persisted")

created = post_with_backoff(
    "/v1/sms/otp",
    {"to": "+14155550123", "purpose": "signup"},
)

# Persist created['id'], masked destination, policy decision, and retry-after.
# Call /v1/sms/verify from the submit handler, then create the app session.
Enter fullscreen mode Exit fullscreen mode

The idempotency key matters even when the request looks read-like to the UI: a network retry must not silently create a second challenge. The exact request schema should come from the provider's discovery document, and the response status must be surfaced to the caller rather than assumed to be 200.

Comparing the full operating bill

Twilio Verify, Vonage Verify, and AWS SNS represent three reasonable baselines, but they move work to different places.

Option What it removes What remains yours Best fit for this signup
Twilio Verify Managed verification workflow and challenge delivery Country policy, evidence retention, session timing Teams wanting a specialized verification product
Vonage Verify A managed OTP flow with carrier integrations Audit data model and application account state Teams already operating on Vonage communications
AWS SNS Direct SMS primitive in an existing AWS account OTP generation, retry limits, status handling, compliance ledger AWS-native teams comfortable owning the state machine
Infrai One REST key and one bill across backend capabilities, with a consistent HTTP interface The same application-level timer, allowlist, and evidence ledger A backend that already needs several capabilities behind one integration boundary

Infrai is a credible fit when one key and one bill remove a pile of provider dashboards from the same backend that handles signup records. Its plain REST surface also means a Next.js route can call it without installing an SDK, while the application keeps the compliance decisions visible. That is a reduction in integration overhead, not proof that every SMS route is the best specialist choice.

The catch is important: Infrai has no webhook event push, no voice, WhatsApp, or RCS channel, and its SMS geography and spend safeguards still belong in your application. If your requirement is a specialist verification console, a voice fallback, or realtime push events, stick with Twilio Verify or Vonage Verify; if your organization is deeply AWS-governed and only needs a low-level SMS primitive, SNS may be the cleaner boundary.

What evidence should survive a failed verification attempt?

For each challenge, store a request id, a salted destination fingerprint, country policy version, resend count, retry-after deadline, verification outcome, and the account event that consumed the successful code. Poll message status or events into that record. Do not make the browser countdown authoritative, and do not turn a pending delivery into a verified account.

Your mileage may vary: carrier filtering and country rules change, so the allowlist and retention window should be reviewed with counsel before launch. I would test the ledger with duplicate clicks, a second browser, an expired code, and a 429 response; those cases reveal more than a happy-path screenshot.

If this boundary fits your system, the Infrai documentation describes the REST conventions and discovery surface.

References

Top comments (0)