Aanvraag Token Exchange
De Client initieert een token exchange verzoek richting het Token Endpoint (zie het Discovery Endpoint).
Dit token request bevat volgende parameters:
Parameter | Omschrijving | |
---|---|---|
grant_type | VERPLICHT | Waarde die verplicht “urn:ietf:params:oauth:grant-type:token-exchange” is |
subject_token | VERPLICHT | Access of refresh token, uitgegeven aan de frontend applicatie |
subject_token_type | VERPLICHT | subject_token type (“urn:ietf:params:oauth:token-type:access_token” of “urn:ietf:params:oauth:token-type:refresh_token” |
audience | OPTIONEEL(*) | Client-id die de audience (de API) uniek identificeert |
resource | OPTIONEEL(*) | URI (die begint met http) die de audience (de API) uniek identificeert |
scope | OPTIONEEL | de scopes (gescheiden door een spatie) die nodig zijn om de API te bevragen |
requested_token_type | OPTIONEEL | Het gewenste token type. Mogelijke waarden: “urn:ietf:params:oauth:token-type:access_token” (default) of “urn:ietf:params:oauth:token-type:jwt” |
actor_token | OPTIONEEL | Extra token, waarvan de gelinkte gebruiker als actor wordt geregistreerd |
actor_token_type | AFHANKELIJK | moet “urn:ietf:params:oauth:token-type:access_token” zijn. Deze waarde is verplicht indien actor_token gespecifieerd werd, zoniet dan is dit verboden |
(*) één van beide is verplicht, want anders heeft de token exchange geen meerwaarde
Toelichting bij een aantal optionele parameters:
audience
De audience is een unieke identifier voor de API. Een Client kan een access token opvragen voor een specifieke audience op voorwaarde dat die audience de Client effectief vertrouwt: er wordt dan een access token aangemaakt voor die audience namens de aangemelde gebruiker. De vertrouwensrelatie tussen API en Client dient bij de opzet van de API expliciet gedefinieerd te worden opdat deze Token Exchange mogelijk zou zijn.
resource
Een resource is een absolute URL die een API uniek identificeert. De URLs die hier gebruikt kunnen worden, dienen vooraf geregistreerd te worden bij de intake van de API. Deze resource-parameter is nuttig indien de Client geen notie heeft van de ClientID, maar wel weet welke resource hij nodig heeft (welke URL hij wil benaderen).
Noot
Wanneer zowel audience als resource ontbreken, zal het uitgeleverde access token enkel geldig zijn voor de Client (waarbij de Token Exchange dan feitelijk zinloos is).scope
Via de scope parameter kan men de scopes (gescheiden door een spatie) aanvragen die aan het uitgeleverde access token gekoppeld moeten worden. Het is mogelijk dat de uitgeleverde scopes verschillen van de gevraagde scopes: enkel scopes die geldig zijn voor alle gevraagde (geldige) audiences én waarvoor de gebruiker over de correcte rechten beschikt zullen worden uitgeleverd.
Wanneer geen scope gespecifieerd werd in het request, worden de scopes van het subject_token gevalideerd.
Tip
U kan er best naar streven om de scopes en audiences zo granulair mogelijk te maken. Het is beter om meerdere access tokens te vragen dan één access token met een te breed toepassingsgebied: deze best-practice verhoogt de veiligheid.requested_token_type
Bij token exchange vraagt men standaard een access token aan voor de opgegeven audience (dus met requested_token_type “urn:ietf:params:oauth:token-type:access_token”). Hierbij ontvangt men een access token, waarmee men de verdere info kan bevragen op het introspectie endpoint.
Indien als requested_token_type “urn:ietf:params:oauth:token-type:jwt” wordt gevraagd, dan zal er in plaats van een (opaque) access token meteen een JWT uitgeleverd worden, waarin alle informatie meteen aanwezig is. Het is zinloos om deze JWT nogmaals naar het introspectie endpoint te sturen (bovendien zal deze introspectie sowieso falen): alle benodigde informatie zit immers reeds in de JWT. Om te valideren dat deze JWT wel degelijk van de Authorization Server van Toegangsbeheer afkomstig is, kan men de signature ervan valideren: de keys waarmee het JWT is getekend, kan je terugvinden op het keys endpoint (zie het Discovery Endpoint).
Tip
Het gebruik van opaque access tokens geniet de voorkeur omdat dit een referentie is naar de relevante info. Een JWT bevat alle info en is als het ware een “kopie” van de data. Een opaque token geeft dus meer controle en kan op elk moment ongeldig gemaakt worden. Een JWT blijft geldig tot het verloopt (“exp”). In geval van een JWT kan de info ook aan iedereen doorgegeven worden. Bij een opaque access token dient een client zich bovendien correct te authenticeren alvorens de info beschikbaar wordt gemaakt.actor_token
Wanneer een actor_token wordt gespecifieerd, maakt de Client duidelijk dat er een delegatie gebeurt. In dat geval zal een act claim toegevoegd worden aan de claims van het access token.
Een request zonder actor_token, maakt het voor de API onmogelijk om een onderscheid te maken tussen de gebruiker of een actor. In dat geval spreken we van impersonatie
De act claim maakt aan de API duidelijk dat de actor optreedt in naam van de gebruiker, maar dat de gebruiker niet zelf het request naar de API stuurt. Wanneer de delegatie gebeurt door een client, zal voor deze client de client_credentials grant toegestaan moeten worden (vraag dit dan aan bij het integratieteam).
Daarna kan de client via de client credentials grant een token aanvragen met de scope delegation. Deze speciale scope bevat geen informatie, maar heeft tot doel om een actor token te kunnen aanvragen dat gebruikt kan worden tijdens de token exchange.
chaining van actor_tokens
Een access token dat bekomen werd na een token exchange, kan zelf opnieuw gebruikt worden als subject_token in een token exchange, al dient het initiële token dat gebruikt werd voor de token-exchange uitgeleverd te zijn na een OpenID Connect authenticatie. Wanneer bij een dergelijke keten van token exchanges telkens een actor token wordt meegegeven, zal dit ook worden weergegeven op het introspection endpoint. Een act claim zal dan op zijn beurt opnieuw een act claim bevatten, die de keten weergeeft.
{
"act": {
"sub": "8fc3bf07-d041-4868-8790-7d5206a64562",
"act": {
"sub": "afddd7fc-b23f-11eb-99ed-03dd47f3aa67"
}
}
}
Uiteraard gelden voor de hele ketting dezelfde voorwaarden als voor één token exchange: de trust relatie tussen de Client en de API en de autorisatie van de gebruiker voor het gebruik van de API en toekenning van de juiste scopes gelden voor iedere stap in deze ketting.
Authenticatie
De Client dient zich te authenticeren zodat
- De OP kan valideren dat het subject token werd uitgeleverd aan de Client
- De vertrouwensrelatie tussen de Client en de audience(s) (API) gevalideerd kan worden
- Het toepassingsgebied van het subject_token niet ongewenst kan uitgebreid worden met het toepassingsgebied van de API
Token exchange is dus niet bruikbaar voor Clients die hun secret niet geheim kunnen houden (bvb. public clients). Zij dienen de flow namens een gebruiker te volgen, waar de integriteit van de requests kan gegarandeerd worden door gebruik te maken van PKCE.
Client authenticatie op basis van ClientID en Secret
Hierbij wordt er bij de onboarding een ClientID en een Secret gegenereerd langs de Authorization Server zijde en aan de Client bezorgd. Deze ClientID en Secret kunnen door de Client op 2 verschillende manieren aangeboden worden aan het Token Endpoint.
Tip
De secret dat bij de client hoort, dient uiterst confidentieel gehouden te worden. Wanneer je secret (mogelijks) gelekt werd, kan je best contact opnemen om een nieuw secret te laten genereren.ClientID en Secret via POST-parameters
Hierbij worden de ClientID en de Secret via POST-parameters doorgestuurd.
Voorbeeld:
POST /op/v1/token HTTP/1.1
Host: authenticatie.vlaanderen.be
Content-Type: application/x-www-form-urlencoded
client_id=28358814-5c20-4c13-bbff-db5dd8c4ae93&
client_secret=CgNjSBQwSolxUcFe7A0U-16j7uccp34-Z5eigKOoCpn5WMHjcb0IkseYA8zhMdYKlpzNJh4Qj4OhjvkVEXq6clvKlutFv5H&
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=Bokejssjdej34jkzbd5shsjSQdxjbdn2kdoveicj47k&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
audience=37f875cb-a7bd-4724-ac39-4729092f8412&
scope=AppRead
Tip
Het doorsturen van de ClientID en Secret via Querystring parameters (dus in de Request URI) is onveilig en wordt bijgevolg niet ondersteund. Wanneer dit toch is gebeurd, kan u best contact opnemen om een nieuw secret te laten genereren.ClientID en Secret via Basic Authentication
De ClientID en Secret worden via Basic Authentication “Authorization”-header meegestuurd.
POST /op/v1/token HTTP/1.1
Host: authenticatie.vlaanderen.be
Authorization: Basic MjgzNTg4MTQtNWMyMC00YzEzLWJiZmYtZGI1ZGQ4YzRhZTkzOkNnTmpTQlF3U29seFVjRmU3QTBVLTE2ajd1Y2NwMzQtWjVlaWdLT29DcG41V01IamNiMElrc2VZQTh6aE1kWUtscHpOSmg0UWo0T2hqdmtWRVhxNmNsdktsdXRGdjVI
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=Bokejssjdej34jkzbd5shsjSQdxjbdn2kdoveicj47k&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
audience=37f875cb-a7bd-4724-ac39-4729092f8412&
scope=AppRead
Client authenticatie via een JWT token
In dit geval genereert de Client bij de onboarding een asymmetrisch keypaar en bezorgt de Authorization Server het publieke deel ervan: het private deel wordt enkel lokaal op de Client bewaard.
Bij de authenticatie op het Token Endpoint worden volgende parameters meegestuurd:
- “client_assertion_type” met als waarde “urn:ietf:params:oauth:client-assertion-type:jwt-bearer”
- “client_assertion” met daarin één enkele JWT
Voorbeeld:
POST /op/v1/token HTTP/1.1
Host: authenticatie.vlaanderen.be
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=Bokejssjdej34jkzbd5shsjSQdxjbdn2kdoveicj47k&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
audience=37f875cb-a7bd-4724-ac39-4729092f8412&
scope=AppRead&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyODM1ODgxNC01YzIwLTRjMTMtYmJmZi1kYjVkZDhjNGFlOTMiLCJzdWIiOiIyODM1ODgxNC01YzIwLTRjMTMtYmJmZi1kYjVkZDhjNGFlOTMiLCJhdWQiOiJodHRwczovL2F1dGhlbnRpY2F0aWUudmxhYW5kZXJlbi5iZS9vcCIsImV4cCI6MTU5MjIwODA2MCwianRpIjoiRGt6bmpzdTQzZHprZDN6amQ1IiwiaWF0IjoxNTkyMjA4MDAwfQ.3dPodaVhJ2d3cXWn0v2YGeZqs5XScJF2lm4MaweDnf4
In bovenstaand request bevatte “client_assertion” een JWT met volgende inhoud:
{
"iss": "28358814-5c20-4c13-bbff-db5dd8c4ae93",
"sub": "28358814-5c20-4c13-bbff-db5dd8c4ae93",
"aud": "https://authenticatie.vlaanderen.be/op",
"exp": 1592208060,
"jti": "Dkznjsu43dzkd3zjd5",
"iat": 1592208000
}
De JWT in de client_assertion dient uiteraard gesigned te zijn met één van de keys die voor die Client geregistreerd staan op de Authorization Server.
Daarnaast moet/kan deze JWT volgende claims bevatten:
Claim | Omschrijving | |
---|---|---|
iss (issuer) | VERPLICHT | Deze dient de ClientID te bevatten |
sub (subject) | VERPLICHT | Deze dient de ClientID te bevatten |
aud (audiance) | VERPLICHT | Deze dient de issuer te bevatten, zijnde https://authenticatie-ti.vlaanderen.be/op voor TEST of https://authenticatie.vlaanderen.be/op voor PROD |
exp (expiration time) | VERPLICHT | Een expiration time moet aanwezig zijn: de huidige tijd mag niet recenter zijn dan de expiration time en deze mag ook niet te ver in de toekomst liggen (maximum 10 minuten) |
jti (jwt id) | OPTIONEEL | AANBEVOLEN Men kan een unieke ID meegeven voor de JWT: de Authorization Server kan dit gebruiken om replay attacks tegen te gaan |
iat (issued at) | OPTIONEEL | Tijdstip waarop de JWT werd gegenereerd: deze mag niet te ver in de toekomst liggen |
nbf (not before) | OPTIONEEL | Indien aanwezig worden tokens niet aanvaard voor de aangegeven timestamp |