Verification flow

Emnet uses a redirect flow: you start a session, the user authenticates with the provider, and you exchange the returned code for verified claims.

The flow end to end

1
Your server → Emnet. Request an authorization URL. You receive authorizeUrl and state.
2
You store the state against the user’s session, then redirect them to authorizeUrl.
3
User ↔ Fayda. They authenticate and consent. Nothing in this step touches your servers, and their credentials never reach Emnet either.
4
Fayda → your redirect URL with code and state.
5
Your server → Emnet. Compare the returned state with the stored one, then exchange the code. You receive a VerifiedIdentity.

Step 1 — start a session

Java
AuthorizeUrlResponse start = emnet.startPersonVerification();
Response
{
  "authorizeUrl": "https://…/authorize?client_id=…&state=a7f3d21c9b0e",
  "state": "a7f3d21c9b0e4f8a1c2e9b7d6a5c3e1f"
}

authorizeUrl is single-use and time-limited. Redirect promptly rather than caching it, and never reuse one across users.

Step 2 — store the state, then redirect

state is the thread that ties the redirect back to the user who began it. Store it server-side against that user’s session and compare it when they return.

Store then redirect
session.setAttribute("emnetState", start.state());
response.sendRedirect(start.authorizeUrl());
Comparing state is not optional

Without it, an attacker can complete their own verification and hand the resulting callback URL to your user, attaching their verified identity to your user’s account. Reject any callback whose state is missing, unknown or does not match. Remove the stored value once used, so a callback cannot be replayed.

Step 5 — exchange the code

This call needs a secret key and must run on your server. A publishable key here gets 403.

Java
if (!state.equals(session.getAttribute("emnetState"))) {
    return badRequest();           // reject, do not continue
}
session.removeAttribute("emnetState");

VerifiedIdentity identity = emnet.completePersonVerification(code, state);

The code is single-use. Exchanging it twice returns 400 — if you need the result again, read the session instead of re-exchanging.

Reading a session later

Session lookup returns status and metadata, never claims. It is for reconciliation — checking whether a verification you started ever completed.

Java
VerificationSessionView view = emnet.getSession(4711L);
view.status();   // e.g. "COMPLETED"

Sessions belong to the account that created them. Requesting another tenant’s session returns 404, not 403 — the API will not confirm that someone else’s session exists.

Cases to handle

What happenedWhat you seeWhat to do
User abandons the flowThey never come back; no callback arrivesNothing to clean up. The session expires on its own and is not billed. Let them start again.
User denies consentCallback arrives without a usable code, or the exchange returns 400Treat as “not verified”, explain what consent is needed for, and offer a retry.
State does not matchYour own comparison failsReject the callback and log the event. Do not verify the user.
Code already used400 from the exchangeYou are handling a duplicate callback. Read the session instead.
Provider unavailable503 with Retry-AfterBack off and retry the start call. Do not treat as verification failure.
Rate limited429 with Retry-AfterBack off — see rate limits.

Practical notes

  • Redirect URLs are registered. Emnet only redirects to URLs on your account, so an attacker cannot point the flow at their own site.
  • Start on the server. You can start a verification from a browser with a publishable key, but the exchange always happens server-side.
  • One session per attempt. If a user restarts, start a new session rather than reusing an old authorizeUrl.
  • Don’t block your signup on it. Treat verification as a step that can be resumed — users lose network connections and close tabs mid-flow.

Next: what a verified identity contains.