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
stateen 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 weopenid profile.Gebruik PKCE: maak een willekeurige
code_verifieren stuur de SHA-256-hash ervan mee alscode_challenge, metcode_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:loginlaat het lid opnieuw inloggen,consentvraagt altijd om toestemming, ennonetoont 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_typeis nietcode.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 eencode_challenge_methodanders danS256, of een ongeldigepromptofmax_age.access_denied: het lid heeft op Weigeren geklikt.login_requiredofconsent_required: metprompt=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_urimee.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, decode_verifierpast niet bij decode_challenge, je app is vergrendeld of het lid is niet meer actief.invalid_request: er ontbreekt iets, zoals decode, of decode_verifierbij een openbare app.unsupported_grant_type:grant_typeis nietauthorization_codeofrefresh_token.unauthorized_client: je app mag dezegrant_typeniet gebruiken, bijvoorbeeldrefresh_tokenzonder 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_inenexpires_at: wanneer het access token verloopt, in seconden vanaf nu en als tijdstip. Let op!expires_atis 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 Legacyurn:congressus:nl.sub: het ID van het lid in Congressus.aud: de Client ID van je app.name,genderenstatus_id: de naam, het geslacht en het ID van de huidige lidstatus van het lid.nonce: denoncedie je in stap 1 meestuurde.exp,iatenauth_time: wanneer het access token verloopt, wanneer dit token is uitgegeven en wanneer het lid inlogde.acrenamr: altijdurn:c2id:acr:silveren["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.
