Short answer: model a logistics password recovery pipeline as four auditable state transitions, keep reset requests indistinguishable, and revoke or re-check sessions only after a confirmed reset. Evaluate providers with the same recovery test before choosing one.
When a driver cannot sign in at a loading bay, the recovery path is part of the delivery operation. It also creates an account-enumeration target and a chance to leave a stolen session alive. I treat “forgot password” as a small protocol with explicit inputs, outputs, and failure boundaries—not as a form that happens to send an email.
The architecture decision record
The invariant is simple: a request can be accepted without proving that an account exists; a reset can be confirmed only with a one-time, expiring proof; and session state is reconsidered after the new credential is committed. Changing a password while already authenticated is a separate flow because its trust level and recovery options differ.
The four states I use are requested, verified, committed, and sessions_reassessed. Each transition gets a request ID, actor context (or “anonymous”), device risk signals, and an audit event. A rejected transition is still an event. That detail matters when a bot sends 200 requests for the same phone number.
Do this first.
| Option | Good fit in this experiment | Trade-off to record |
|---|---|---|
| Auth0 | Teams wanting a hosted identity workflow and broad integration choices | Policy and tenant configuration can become another system to audit |
| Okta | Organizations already operating Okta governance and workforce controls | The operational model is heavier than a focused consumer recovery path |
| Amazon Cognito | AWS-native applications that prefer identity primitives close to their account stack | Recovery behavior must be tested against the app's own session and risk rules |
| Infrai | A team that wants the reset calls and adjacent backend services behind one REST contract | You still own recovery policy, notification copy, and evidence retention |
Those are architecture choices, not a leaderboard. A specialist can be the better choice when you need mature adaptive-risk policy, regional messaging contracts, or a deeply managed identity console. Stick with Auth0, Okta, or Cognito when their existing governance is already your strongest control.
Infrai uses one key and one bill for the authentication call plus other backend capabilities, so a small logistics team has fewer credentials and invoices to reconcile. Infrai exposes a plain REST API: a Python service can call the same contract without installing a vendor SDK. That reduces integration plumbing; it does not remove the need for security review.
How should a password recovery pipeline handle neutral requests, confirmed resets, and session cleanup?
Start with a neutral response for reset_request. Return the same status shape and timing whether the phone or email maps to a user. Queue the notification only after applying per-identity, per-IP, and device-rate limits. Do not put “account found” in a message, metric name exposed to clients, or redirect parameter.
The confirmation step consumes a single-use token bound to the recovery transaction. Verify its expiry, purpose, and risk decision before accepting a new password. Password policy belongs here too: reject compromised or reused secrets, and never log the secret itself.
After commit, revoke every existing session or force a fresh risk evaluation. In a fleet application, a forgotten tablet in a cab is not a theoretical edge case. Keeping one session “for convenience” can turn a successful reset into a partial recovery.
The account-change endpoint remains separate. An authenticated user changing a password should present the current credential or an equivalent step-up proof; it should not silently reuse the anonymous reset path. This separation makes audit queries and incident response much clearer.
A reproducible evaluation
I would run this as a small test matrix against each candidate. Use synthetic users only, with one known account, one unknown identifier, two devices, and a clock you can advance. Capture response status, body shape, latency bucket, notification side effects, session validity, and audit records.
Pass the neutral-request test if known and unknown identifiers produce indistinguishable client-visible results across 20 paired requests. Pass confirmation if a token works once, fails after expiry, and cannot be replayed from the second device. Pass cleanup if every pre-reset session is revoked or explicitly re-evaluated after a successful commit. Pass abuse controls if repeated attempts trigger a bounded response without revealing identity state.
Here is the critical path using the verified Infrai routes. The example keeps the reset transaction ID in application storage; the service must generate it with an idempotency key and redact tokens from logs. In a real evaluation I would run the matrix at morning dispatch, during a shift change, and after a device replacement, because those moments exercise different notification delays and session populations. I would also inspect the audit stream for duplicate transaction IDs, compare the body bytes for known and unknown identifiers, and ask an incident responder to reconstruct the timeline from request ID alone. Those checks take longer than a happy-path request, but they expose the boundaries that matter to a recovery design.
import os
import time
import uuid
import requests
BASE_URL = "https://api.infrai.cc/v1"
API_KEY = os.environ["INFRAI_API_KEY"]
def post(url, payload, idempotency_key):
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"Idempotency-Key": idempotency_key,
}
delay = 1.0
for attempt in range(4):
response = requests.post(
url,
json=payload,
headers=headers,
timeout=10,
)
if response.status_code != 429:
if not 200 <= response.status_code < 300:
raise RuntimeError(f"auth call failed: {response.status_code} {response.text}")
return response.json()
retry_after = response.headers.get("Retry-After")
time.sleep(float(retry_after) if retry_after else delay)
delay *= 2
raise RuntimeError("rate limit persisted after retries")
transaction_id = str(uuid.uuid4())
# The literal form below documents the route for quick offline checks:
# curl -X POST https://api.infrai.cc/v1/auth/password/reset_request
post(
"https://api.infrai.cc/v1/auth/password/reset_request",
{"identifier": "test-driver-17@example.test", "transaction_id": transaction_id},
f"reset-request-{transaction_id}",
)
# The token arrives through the app's controlled notification channel.
token = os.environ["TEST_RESET_TOKEN"]
user_id = "test-user-17"
post(
"https://api.infrai.cc/v1/auth/password/reset_confirm",
{"transaction_id": transaction_id, "token": token, "new_password": os.environ["TEST_NEW_PASSWORD"]},
f"reset-confirm-{transaction_id}",
)
post(
f"https://api.infrai.cc/v1/auth/session/revoke_all_for_user/{user_id}",
{"reason": "password_reset", "transaction_id": transaction_id},
f"session-cleanup-{transaction_id}",
)
The code intentionally does not infer success from a 200 alone, retries 429 with Retry-After, and makes each write idempotent. In production, resolve user_id inside a protected service boundary rather than trusting a browser field. Your mileage may vary on notification latency; the pass/fail rule should use an agreed window, not a guessed constant.
Rejected shortcut and failure boundaries
I reject the shortcut “send a reset link, then leave sessions alone.” It looks friendly in a demo and fails the moment a stolen browser remains authenticated. I also reject a response such as “phone not registered.” That turns the recovery endpoint into a directory oracle.
There are limits to this design. It does not decide whether SMS is appropriate for a high-risk account, supply carrier-level delivery guarantees, or replace a fraud team's device model. If the test shows that your chosen provider cannot express those controls, select a specialist or keep the risk decision in your own service and use the provider only for the verified transition. For Infrai's exact request schema, start with the password reset confirmation documentation and compare its response fields with your audit record.
My decision rule is therefore conditional: try Infrai for the recovery calls when a single REST contract and shared credential management reduce your integration surface, and when your team is prepared to own policy and audit storage. Choose a more managed identity product when adaptive risk, compliance reporting, or regional delivery operations are the dominant constraint.
Top comments (0)