Inloggen met BeID (OIDC)

BeID is een OpenID Connect-provider. Je gebruikt de Authorization Code-flow met PKCE — de aanbevolen flow voor zowel web-apps als publieke clients (SPA's, mobiel).

Endpoints

Lees deze bij voorkeur uit het discovery-document in plaats van ze hard te coderen.

GET/.well-known/openid-configuration
Discovery-document met alle endpoints en ondersteunde algoritmen.
GET/.well-known/jwks.json
Publieke sleutels (JWKS) om token-handtekeningen te verifiëren.
GET/oauth/authorize
Start de flow; de gebruiker authenticeert en je krijgt een code terug.
POST/oauth/token
Wissel de code in voor een id_token en access_token.
GET/oauth/userinfoBearer token
Haal de claims van de ingelogde gebruiker op.

Stap 1 — PKCE voorbereiden

Genereer een code_verifier en daaruit een code_challenge (SHA-256, base64url). De challenge stuur je mee naar /oauth/authorize, de verifier pas naar /oauth/token.

JavaScript
import { randomBytes, createHash } from "node:crypto";

const verifier = randomBytes(32).toString("base64url");
const challenge = createHash("sha256").update(verifier).digest("base64url");

Stap 2 — Authorize

Redirect
GET https://id.becyber.nl/oauth/authorize
  ?client_id=beid_client_xxx
  &redirect_uri=https://jouw-app.nl/callback
  &response_type=code
  &scope=openid profile email kyc
  &state=<random-csrf-token>
  &code_challenge=<challenge>
  &code_challenge_method=S256

Gebruik altijd state

Geef een willekeurige state mee en controleer die bij de callback. Zo bescherm je tegen CSRF op de redirect.

Stap 3 — Token-uitwisseling

POST /oauth/token
{
  "grant_type": "authorization_code",
  "code": "<code uit de callback>",
  "redirect_uri": "https://jouw-app.nl/callback",
  "client_id": "beid_client_xxx",
  "code_verifier": "<verifier uit stap 1>"
}

Het antwoord bevat een ondertekend ID-token:

200 OK
{
  "access_token": "eyJhbGciOiJFZERTQS0...",
  "id_token": "eyJhbGciOiJFZERTQS0...",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "openid profile email kyc"
}

Stap 4 — Token valideren

Verifieer elk token voordat je het vertrouwt:

  • Handtekening tegen de JWKS (let op de kid in de header).
  • iss = https://id.becyber.nl
  • aud = jouw client_id
  • exp nog niet verstreken
JavaScript (jose)
import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://id.becyber.nl/.well-known/jwks.json"),
);

const { payload } = await jwtVerify(id_token, JWKS, {
  issuer: "https://id.becyber.nl",
  audience: CLIENT_ID,
});
// payload.sub, payload.email, payload.kyc_status, ...

Refresh tokens

Vraag de scope offline_access aan om naast het access-token ook een refresh-token te krijgen. Daarmee verleng je de toegang zonder de gebruiker opnieuw te laten inloggen.

POST /oauth/token (refresh)
{
  "grant_type": "refresh_token",
  "refresh_token": "<refresh-token>",
  "client_id": "beid_client_xxx"
}

Rotatie & hergebruik-detectie

Elk refresh-token is eenmalig: bij gebruik krijg je een nieuw token en wordt het oude ingetrokken (rotatie). Wordt een al geroteerd token toch hergebruikt, dan beschouwt BeID dat als een lek en trekt alle refresh-tokens van die gebruiker bij die app in.

Intrekken (RFC 7009)

Trek een refresh-token actief in via het revocation-endpoint:

POST /oauth/revoke
{ "token": "<refresh-token>", "client_id": "beid_client_xxx" }

Claims

ClaimBetekenis
subUnieke, stabiele gebruikers-id
emailE-mailadres
email_verifiedOf het e-mailadres geverifieerd is
nameVolledige naam
kyc_levelnone · basic · verified
kyc_statusnot_startedapproved
BeID ondertekent standaard met EdDSA (Ed25519). De ondersteunde algoritmen staan in het discovery-document onder id_token_signing_alg_values_supported. Gebruik altijd de JWKS — sleutels kunnen roteren. Meer hierover op Beveiliging.
Inloggen met BeID (OIDC) — BeID Documentatie · BeID