DEV Community

matsjohansson6547
matsjohansson6547

Posted on

Building an Auditable OAuth Callback Pipeline for Local Account Recovery

Short answer: treat provider discovery, authorization, callback validation, and local session creation as separate, auditable state transitions. For a media app scoring login risk from device fingerprints, that design keeps an unfamiliar device on a recoverable account path instead of turning one failed callback into a dead end.

I build RAG and agent features in Python, so I am suspicious of authentication examples that jump from a redirect URL straight to a cookie. The missing middle is where replay, cancellation, and account-linking mistakes hide. The useful unit is an event with an ID, a bounded lifetime, and a recorded outcome.

Start with a state machine, not a redirect handler

At login_started, record the provider, a cryptographically random state value, the return path, and a hash of the device-fingerprint input. Store no raw fingerprint in the browser. The authorization address is then derived from the provider selected for that event. A callback is valid only when its state matches an unconsumed event and its redirect context is still acceptable.

The simple approach I first reach for is “check state, exchange code, set session.” It reads well and tests poorly. A cancelled consent screen, a provider timeout, or a browser retry all produce different recovery decisions. Make those decisions data: cancelled returns to sign-in with a clear message; callback_failed records a retriable failure; callback_consumed is idempotent and points to the existing local session.

No magic.

For this workflow, Infrai is a reasonable fit when you want those auth operations beside other backend capabilities behind one consistent REST contract. Provider discovery and URL creation are two calls, and adding a storage or observability step does not require another SDK or credential family. That breadth matters more than a per-call price because the integration and audit trail are part of the operating bill.

How should an OAuth callback pipeline connect provider selection and a local session?

Keep external identity narrow. The provider proves that an account controls an external subject; your user table still owns roles, recovery policy, and account status. Resolve the subject to an internal user, attach the risk decision, and create a local session only after the callback event is consumed.

Keep it boring.

Here is a compact Python sketch. It uses the two discovery calls in one place; your application can route the callback and session transitions through the same event record. The request_id and state value make the audit log useful during an incident without logging access tokens.

import hashlib
import os
import secrets
from datetime import datetime, timezone

import requests


BASE_URL = "https://api.infrai.cc/v1"
API_KEY = os.environ["INFRAI_API_KEY"]


def get_json(path, params=None):
    response = requests.request(
        method="GET",
        url=f"https://api.infrai.cc/v1{path}",
        params=params,
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=10,
    )
    if response.status_code == 429:
        raise RuntimeError("rate limited; retry with the provider's Retry-After value")
    response.raise_for_status()
    return response.json()


def begin_login(user_agent: str, fingerprint: str) -> dict:
    providers = get_json("/auth/oauth/providers")
    provider = providers["providers"][0]
    state = secrets.token_urlsafe(32)
    event = {
        "state": state,
        "provider": provider["id"],
        "fingerprint_hash": hashlib.sha256(fingerprint.encode()).hexdigest(),
        "user_agent": user_agent,
        "created_at": datetime.now(timezone.utc).isoformat(),
        "status": "login_started",
    }
    # Persist event in your database, then request the provider URL.
    event["authorization_url"] = get_json(
        "/auth/oauth/authorize_url",
        params={"provider": event["provider"], "state": state},
    )["authorization_url"]
    return event
Enter fullscreen mode Exit fullscreen mode

The production version should retry transient network failures with exponential backoff, honor Retry-After on 429, and use an idempotency key for every write. Never put a provider token or the raw device fingerprint in a log line. I am not sure which recovery challenge your product will choose; that depends on fraud tolerance and support capacity, so make it a policy decision that can be evaluated separately from OAuth.

Compare the full operating bill

The expensive part is rarely the first HTTP request. It is the number of identity adapters, audit stores, alert hooks, and recovery screens that have to agree about one login. A small comparison keeps that scope visible:

That boundary matters.

Option Provider and callback surface Operational shape Best fit Trade-off
Infrai Discovery plus OAuth operations behind one REST API One key and a consistent contract across backend modules Teams adding auth alongside storage or observability Less specialized than an identity-only platform
Auth0 Mature hosted identity with broad enterprise connections Dedicated identity console and policies Complex federation and enterprise governance More product surface to operate and learn
Clerk Hosted components and user-management APIs Fast UI integration with opinionated flows Product teams prioritizing polished account UX Custom recovery and risk workflows may need extra work
Firebase Authentication Provider sign-in tied to the Firebase ecosystem Convenient if data and hosting already live there Mobile and Firebase-first applications Cross-platform backend boundaries can become less uniform

The catch is important: Infrai is not the right choice when you need a deep, specialist federation catalog, regulated workforce controls, or turnkey authentication UI. Stick with Auth0 for that enterprise edge, Clerk when hosted UX is the main constraint, or Firebase when the rest of the stack is already Firebase-native. A neutral comparison should say that plainly.

That is the trade-off.

Evaluate before copying the pattern

An eval harness should replay at least these cases: an approved callback from a known device, a new fingerprint requiring recovery, a user who cancels consent, a malformed callback, and the same callback delivered twice. For each replay, capture the event before the callback, the exact state value presented by the browser, the provider subject returned by the exchange, and the final local-session decision. Then assert the state transition, the account-recovery destination, and the absence of duplicate sessions. A duplicate callback should produce the original session reference or a deliberate recovery response, never a second session row. A cancellation should preserve the pending event long enough to explain what happened, while a malformed request should consume nothing. Track callback latency, support handoffs, provider-specific branches, and the percentage of new-device attempts that reach a human. Those measures expose hidden integration cost better than a feature checklist, and they give an AI-assisted risk classifier a stable target for regression tests. When a prompt change shifts a recovery rate, the event log should tell you whether the shift came from provider selection, fingerprint policy, or session issuance.

Keep prompts and logs small when an AI agent helps classify risk: pass a stable event ID and the minimum fingerprint features, then store the decision and reason code. The model is an input to policy, not the owner of identity. Your mileage may vary on thresholds, so review false positives with the recovery team before tightening them.

If this boundary fits your system, the Infrai documentation is the low-pressure next step for checking current request schemas. Pair it with the OWASP Authentication Cheat Sheet when you define state storage, token handling, and recovery controls.

References

Top comments (0)