Naar de hoofdinhoud

Hoe verloopt Inloggen met Congressus?

De technische stappen van Inloggen met Congressus, van inloggen tot refresh token

Heb je een app aangemaakt (OAuth2 app toevoegen), dan laat je leden in deze stappen inloggen. Staat je app op OpenID Connect, dan doet een standaardbibliotheek dit voor je; zie Inloggen met Congressus via OpenID Connect.

In de voorbeelden is https://www.vereniging.nl de website van je vereniging.

Stap 1: Stuur het lid naar de website van je vereniging

  • Maak een willekeurige state en bewaar die, bijvoorbeeld in een cookie. Je krijgt hem in stap 2 terug.

  • Kies de scopes, gescheiden door spaties, bijvoorbeeld openid profile email. Noem je geen scopes, dan vragen we openid profile.

  • Gebruik PKCE: maak een willekeurige code_verifier en stuur de SHA-256-hash ervan mee als code_challenge, met code_challenge_method=S256. Verplicht voor een openbare app, aangeraden voor elke app.

Stuur het lid dan naar:

https://www.vereniging.nl/oauth/authorize?response_type=code&client_id=<client_id>&scope=openid profile email&state=<state>&code_challenge=<code_challenge>&code_challenge_method=S256

Je kunt ook meesturen:

  • redirect_uri: een van de Redirect-URI's van je app, precies zoals ingesteld. Zonder deze parameter gebruiken we de eerste.

  • nonce: een willekeurige waarde die we in het ID token terugzetten.

  • prompt: login laat het lid opnieuw inloggen, consent vraagt altijd om toestemming, en none toont geen pagina maar stuurt een fout terug als inloggen of toestemming nodig is.

  • max_age: na hoeveel seconden sinds het inloggen het lid opnieuw moet inloggen.

Stap 2: Het lid komt terug

Het lid logt in als dat nodig is en geeft je app toestemming, tenzij je app dat volgens zijn instellingen mag overslaan. Daarna sturen we het lid naar je redirect-URI, met de code en je state:

https://eetmee.vereniging.nl/oauth/return?code=4WOSENHMG4MYCMB5BGGCJXHILVATNVOPXBRODIN3WOOI44XRXLIA&state=<state>

Controleer dat de state dezelfde is als die je in stap 1 bewaarde. Zo weet je dat hetzelfde lid terugkomt.

Er is een fout opgetreden

Dan staat achter je redirect-URI ?error=<fout>&state=<state>. De fout is een van:

  • unauthorized_client: je app is vergrendeld.

  • unsupported_response_type: response_type is niet code.

  • invalid_scope: je vraagt een scope die niet bestaat of die je app niet mag vragen. Scheid scopes met een spatie; een komma geeft deze fout.

  • invalid_request: het verzoek klopt niet, bijvoorbeeld een code_challenge_method anders dan S256, of een ongeldige prompt of max_age.

  • access_denied: het lid heeft op Weigeren geklikt.

  • login_required of consent_required: met prompt=none, als het lid eerst moet inloggen of toestemming moet geven.

Staat de client_id niet bij ons bekend, dan ziet het lid een pagina die niet gevonden is. Noemt een app op OpenID Connect een redirect_uri die niet bij de app staat, dan weigeren we het verzoek.

Stap 3: Ruil de code in voor een token

De code is 60 seconden geldig en werkt één keer. Wordt een code een tweede keer gebruikt, dan trekken we het token van de eerste keer in.

Doe een POST naar https://www.vereniging.nl/oauth/token met Content-Type: application/x-www-form-urlencoded en deze body:

grant_type=authorization_code&code=<code>&code_verifier=<code_verifier>

  • Noemde je in stap 1 een andere dan de eerste redirect-URI, stuur dan dezelfde redirect_uri mee.

  • Een vertrouwelijke app meldt zich aan met HTTP Basic: de Client ID als gebruikersnaam, de client secret als wachtwoord.

  • Een openbare app gebruikt geen HTTP Basic, maar stuurt client_id=<client_id> mee in de body.

Let op! Bij een vertrouwelijke app doet je server dit verzoek, nooit de browser van het lid. Anders lekt je client secret.

Er is een fout opgetreden

Je krijgt JSON terug: {"error": "<fout>"}. De fout is een van:

  • invalid_client: de Client ID of client secret klopt niet, of je app meldt zich aan op een manier die niet bij zijn clienttype past.

  • invalid_grant: de code is verlopen, onjuist of al gebruikt, de code_verifier past niet bij de code_challenge, je app is vergrendeld of het lid is niet meer actief.

  • invalid_request: er ontbreekt iets, zoals de code, of de code_verifier bij een openbare app.

  • unsupported_grant_type: grant_type is niet authorization_code of refresh_token.

  • unauthorized_client: je app mag deze grant_type niet gebruiken, bijvoorbeeld refresh_token zonder Refresh token toestaan.

Je krijgt een token

{
  "access_token": "Het access token",
  "token_type": "bearer",
  "expires_in": 240,
  "expires_at": "2026-11-11 13:46:13.820105",
  "scope": "openid profile email",
  "refresh_token": "Het refresh token, als je app die mag gebruiken",
  "user_id": 1234,
  "name": "De naam van het lid",
  "id_token": "Het ID token, bij de scope openid"
}

  • access_token: hiermee haal je in stap 4 de gegevens van het lid op.

  • expires_in en expires_at: wanneer het access token verloopt, in seconden vanaf nu en als tijdstip. Let op! expires_at is in UTC, niet in Nederlandse tijd.

  • refresh_token: alleen als je app Refresh token toestaan heeft en vertrouwelijk is. Zie stap 5.

  • user_id: het ID van het lid in Congressus. Dit is niet de gebruikersnaam, maar je kunt het gebruiken in de API.

  • id_token: een JWT die zegt welk lid er is ingelogd. Decodeer en controleer hem met een JWT-bibliotheek.

Het ID token bevat:

  • iss: wie het token uitgaf. Bij OpenID Connect het adres van de website, bij Legacy urn:congressus:nl.

  • sub: het ID van het lid in Congressus.

  • aud: de Client ID van je app.

  • name, gender en status_id: de naam, het geslacht en het ID van de huidige lidstatus van het lid.

  • nonce: de nonce die je in stap 1 meestuurde.

  • exp, iat en auth_time: wanneer het access token verloopt, wanneer dit token is uitgegeven en wanneer het lid inlogde.

  • acr en amr: altijd urn:c2id:acr:silver en ["pwd"].

Een app op OpenID Connect krijgt een ID token dat met RS256 is ondertekend; de sleutel staat op https://www.vereniging.nl/.well-known/jwks.json. Een app op Legacy krijgt een ID token dat met HS256 is ondertekend, met de client secret als sleutel.

Stap 4: Haal de gegevens van het lid op

Doe een GET naar https://www.vereniging.nl/oauth/userinfo met de header:

Authorization: Bearer <access_token>

Je krijgt de gegevens van het lid als JSON, alleen voor de scopes die het lid gaf. Welke velden elke scope geeft, lees je in Welke scopes zijn er beschikbaar? Hiervoor heb je de scope openid nodig; zonder krijg je 403 met insufficient_scope. Een verlopen of ingetrokken token geeft 401 met invalid_token.

Stap 5: Vraag een nieuw access token aan met het refresh token

Een access token verloopt na de Access token geldigheid van je app. Wil je daarna nog gegevens van het lid ophalen, bijvoorbeeld om ze op de achtergrond bij te werken, dan vraag je met het refresh token een nieuw access token aan. Het lid hoeft daar niets voor te doen.

Dat kan als je app Refresh token toestaan aan heeft staan en vertrouwelijk is. Doe een POST naar https://www.vereniging.nl/oauth/token, met HTTP Basic zoals in stap 3 en deze body:

grant_type=refresh_token&refresh_token=<refresh_token>

Je krijgt een antwoord zoals in stap 3, met een nieuw access token. Het refresh token blijft hetzelfde. Het werkt tot je het intrekt (stap 6), je app vergrendeld wordt of het lid niet meer actief is.

Let op! Een refresh token geeft blijvend toegang tot de gegevens van een lid. Deel het nooit met gebruikers en bewaar het veilig, net als je client secret.

Stap 6: Trek een token in

Logt een lid uit bij je applicatie, of heb je een token niet meer nodig, trek het dan in. Doe een POST naar https://www.vereniging.nl/oauth/revoke, met dezelfde aanmelding als in stap 3 en deze body:

token=<access_token of refresh_token>

Het access token en het refresh token werken daarna allebei niet meer. Je krijgt {"success": "deleted_token"} terug.

Gerelateerde artikelen

Was dit een antwoord op uw vraag?