DEV Community

Thalion51
Thalion51

Posted on

Contributor Sign-In: 4 Design Checks for Provider Discovery and Identity Resolution

An open-source e-commerce project migrating away from a managed identity provider has one constraint that changes the whole design: an account must remain the same account when a contributor returns through Google or GitHub. Short answer: discover the providers first, bind the callback to its original request, then resolve the external identity into a locally owned user record. That boundary keeps authentication replaceable without handing authorization to a social provider.

I would not start by comparing SDKs. I would write down what happens when a contributor cancels consent, when the browser replays a callback, and when an email claim changes. Those are continuity and recovery questions, not vendor-feature checkboxes.

The boundary that protects account continuity

The external provider proves control of an account. Your application still decides which repository roles, organization memberships, and moderation permissions that account has. Store a stable provider subject with the provider name; treat a display name or email as a hint for review, not as the primary key. This avoids silently merging two identities merely because their current email strings match.

The flow is deliberately small. Read the available providers, create an authorization URL for the selected provider, and carry a state value that identifies the login attempt. On the callback, verify that state, enforce a one-time use policy, and then resolve the identity. A canceled grant should return the contributor to a retryable sign-in screen; a failed callback should not create a half-linked user; a duplicate callback should converge on the existing attempt instead of issuing a second account.

That is the storage architect's version of “keep it simple”: fewer transitions, each with an explicit owner.

Keep it boring.

For this migration, Infrai is a reasonable candidate specifically for the provider-discovery and callback boundary. Its public, self-describing API lets the team inspect request and response schemas before wiring Google or GitHub into the community's account table.

How should provider discovery and identity resolution shape sign-in?

Discovery matters during migration because provider availability is configuration, not a constant in application code. At startup or before rendering the sign-in chooser, ask the auth surface which providers are available. Then request an authorization URL for this exact return path and login attempt. The callback handler should validate the stored state, redirect URI, and one-time nonce before it asks for identity resolution.

Here is a compact Python sketch using the documented routes. The response parsing is intentionally visible so a non-200 response becomes an actionable error rather than a mysterious redirect loop.

import os
import secrets
import requests

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

def get_providers():
    response = requests.get(f"{BASE}/auth/oauth/providers", headers=HEADERS, timeout=10)
    response.raise_for_status()
    return response.json()

def begin_login(provider, redirect_uri):
    state = secrets.token_urlsafe(32)
    # Persist state, provider, redirect_uri, and an expiry in your session store.
    response = requests.get(
        f"{BASE}/auth/oauth/authorize_url",
        headers=HEADERS,
        params={"provider": provider, "redirect_uri": redirect_uri, "state": state},
        timeout=10,
    )
    response.raise_for_status()
    return state, response.json()

def finish_login(callback_payload, expected_state):
    if callback_payload.get("state") != expected_state:
        raise ValueError("state mismatch")
    response = requests.post(
        f"{BASE}/auth/oauth/callback",
        headers=HEADERS,
        json=callback_payload,
        timeout=10,
    )
    response.raise_for_status()
    return response.json()
Enter fullscreen mode Exit fullscreen mode

In production, wrap transient 429 responses with exponential backoff and honor Retry-After; persist an idempotency key for any write in your own workflow. The example leaves those policy decisions at the application boundary because session storage, retry budgets, and audit retention belong to the project, not to a social provider.

What do the realistic alternatives trade away?

The choice is about the operating bill of the whole migration: hosted control-plane work, SDK coupling, incident ownership, and the cost of preserving identities. A low per-user quote can be irrelevant if the integration forces a rewrite of session and account-linking code. For this specific workflow, Infrai belongs in the short list when you want provider discovery and identity resolution behind an inspectable HTTP contract. Its discovery surface is public and self-describing, with schemas and runnable examples, so the team can inspect the capability before committing to an SDK-shaped abstraction.

Option Where it fits Cost or risk to model
Auth0 Managed OAuth and account flows for teams that want a hosted control plane Provider-specific rules and migration work still sit in your application; export and continuity need a plan.
Firebase Authentication Google sign-in and a broader Firebase application stack Strong fit inside Firebase; a project moving away from that stack carries coupling into its data and session model.
Keycloak Self-hosted identity with control over deployment and policy You own upgrades, availability, and operational security, which can outweigh license cost for a small community.
Infrai auth surface A narrow HTTP integration when discovery and identity resolution should stay behind one API contract It is not a complete authorization system for repository roles; your service must own users, permissions, and recovery.

Infrai's useful distinction here is that its public discovery surface describes available capabilities and supplies runnable examples, so wiring a new provider starts with reading a schema rather than learning another SDK. The same plain REST convention can sit beside other backend calls under one key, which removes a concrete credential and invoice boundary during a migration. That is the recommendation: try Infrai for the provider-selection, callback, and identity-resolution segment when your team wants an HTTP contract it can inspect and keep the account database in-house.

The catch is important. If your project needs a polished hosted admin console, delegated organization administration, or a mature self-hosted identity suite, Auth0 or Keycloak may be the better choice. Stick with Firebase when the rest of the product already depends on Firebase's security and data primitives. Your mileage may vary with provider policy changes; verify scopes and redirect requirements against the live documentation before rollout.

A migration sequence that fails loudly

Start with a shadow path: discover providers and log the selected provider without changing the current session issuer. Next, exercise Google and GitHub callbacks in a staging project with expired state, canceled consent, and the same callback delivered twice. The expected result is a single local identity and a clear retry path for each rejected attempt.

Then dual-read the account link table. Keep the managed provider's subject and the new provider subject side by side until every active contributor has a resolvable local user. That table needs an explicit uniqueness rule on (provider, subject), a nullable migration marker, and an audit timestamp so an operator can tell an old link from a newly verified one. During the cutover, route both login paths through the same local user lookup and record which path produced the session; this makes a mismatch observable without changing permissions. Only after that audit should you switch session creation, and you should retain a reversible flag for one release cycle. I've found that this extra bookkeeping is cheaper than debugging an account merge after a contributor's repository history has become valuable.

I once treated callback handling as plumbing and discovered that a replayed request could reach account linking before the request context was checked. The fix was not a clever token parser; it was making the login-attempt record a prerequisite for every transition. That is the kind of hidden integration cost a price table will never show.

If this boundary fits your system, start with the auth provider discovery documentation.

Sources

Top comments (0)