VVEREID Docs
quickstart

Quickstart — VEREID Auth

Add Login with VEREID to any app in ten minutes using standards-compliant OIDC, with the verified custom claim shipped in your id_token.

Last updated 2026-05-20

VEREID Auth is a hosted OpenID Connect provider that supports the full OAuth 2.1 surface area (auth code + PKCE, refresh, client credentials, device code, PAR, DPoP) plus SAML 2.0 for enterprise federation. The killer feature is the vereid_verification custom claim: every id_token we issue tells you exactly how trusted the signed-in user is.

This quickstart wires Login with VEREID into a generic web app via the authorization-code + PKCE flow.

1. Register an OAuth client

In the developer console create a new Auth app:

  • Client nameMy App (dev)
  • Redirect URIshttp://localhost:3000/auth/callback
  • Grant typesauthorization_code, refresh_token
  • Scopesopenid email profile vereid:verification

You'll receive a client_id and a client_secret. The verification scope is what causes our authorization server to embed the vereid_verification claim in your tokens.

export VEREID_CLIENT_ID=app_••••••••••••
export VEREID_CLIENT_SECRET=cs_••••••••••••

2. Discover the endpoints

Always read the discovery document — never hard-code endpoint URLs. The jwks_uri rotates and you'll break in production if you cache.

curl -sS https://auth.vereid.com/.well-known/openid-configuration | jq .
const disco = await fetch(
  "https://auth.vereid.com/.well-known/openid-configuration",
).then((r) => r.json());

3. Build the authorization URL (PKCE)

import crypto from "node:crypto";
 
const verifier = crypto.randomBytes(32).toString("base64url");
const challenge = crypto
  .createHash("sha256")
  .update(verifier)
  .digest("base64url");
 
// stash `verifier` in a signed cookie or session
const url = new URL(disco.authorization_endpoint);
url.searchParams.set("client_id", process.env.VEREID_CLIENT_ID);
url.searchParams.set("redirect_uri", "http://localhost:3000/auth/callback");
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", "openid email profile vereid:verification");
url.searchParams.set("code_challenge", challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", crypto.randomBytes(16).toString("hex"));
res.redirect(url.toString());
import secrets, hashlib, base64, urllib.parse
verifier = secrets.token_urlsafe(32)
challenge = base64.urlsafe_b64encode(
    hashlib.sha256(verifier.encode()).digest()
).rstrip(b"=").decode()

4. Exchange the code for tokens

curl -sS -X POST https://auth.vereid.com/v1/oidc/token \
  -u "$VEREID_CLIENT_ID:$VEREID_CLIENT_SECRET" \
  -d grant_type=authorization_code \
  -d code="$CODE" \
  -d redirect_uri=http://localhost:3000/auth/callback \
  -d code_verifier="$VERIFIER"
const body = new URLSearchParams({
  grant_type: "authorization_code",
  code,
  redirect_uri: "http://localhost:3000/auth/callback",
  code_verifier: verifier,
});
const tokens = await fetch(disco.token_endpoint, {
  method: "POST",
  headers: {
    Authorization: "Basic " + Buffer.from(`${id}:${secret}`).toString("base64"),
  },
  body,
}).then((r) => r.json());

5. Validate the id_token and read the verification claim

Pull JWKS from disco.jwks_uri, validate iss, aud, exp, and signature with any compliant JWT library (jose for JS, python-jose for Python). Then read the custom claim:

import * as jose from "jose";
 
const jwks = jose.createRemoteJWKSet(new URL(disco.jwks_uri));
const { payload } = await jose.jwtVerify(tokens.id_token, jwks, {
  issuer: disco.issuer,
  audience: process.env.VEREID_CLIENT_ID,
});
 
const v = payload.vereid_verification;
if (v?.tier === "T2" || v?.tier === "T5") {
  console.log("User is verified at", v.tier, "with badges", v.badges);
}

The full claim schema is documented in OIDC claims. The shape is stable across all three product surfaces.

6. Handle logout

Single Logout uses end_session_endpoint from the discovery document:

const url = new URL(disco.end_session_endpoint);
url.searchParams.set("id_token_hint", tokens.id_token);
url.searchParams.set("post_logout_redirect_uri", "http://localhost:3000/");
res.redirect(url.toString());