Aanvraag Token Exchange
De (frontend) toepassing 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 | OIDC 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 Resource) uniek identificeert |
resource | OPTIONEEL(*) | URI (die begint met http) die de audience (de API Resource) uniek identificeert |
scope | OPTIONEEL | de scopes (gescheiden door een spatie) die nodig zijn om de API Resource 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 Resirce. Een (frontend) toepassing kan zijn OIDC access token inwisselen voor API access token door deze op te vragen voor een specifieke audience (API Resource) op voorwaarde dat die audience de (frontend) toepassing effectief vertrouwt: er wordt dan een API access token aangemaakt voor die audience namens de aangemelde gebruiker. De vertrouwensrelatie tussen API Resource en (frontend) toepassing dient bij de opzet van de API Resource expliciet gedefinieerd te worden opdat deze Token Exchange mogelijk zou zijn.
resource
Een resource is een absolute URL die een API Resource uniek identificeert. De URLs die hier gebruikt kunnen worden, dienen vooraf geregistreerd te worden bij de intake van de API Resource. Deze resource-parameter is nuttig indien de (frontend) toepassing geen notie heeft van de ClientID van de APIR Resource, maar wel weet welke resource hij nodig heeft (welke URL hij wil benaderen).
Noot
Wanneer zowel audience als resource ontbreken, zal het uitgeleverde API access token enkel geldig zijn voor de (frontend) toepassing. De client ID van de (frontend) toepassing zal dan als audience in het API access token staan (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 API 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 (API Resources) é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 API access tokens te vragen dan één API access token met een te breed toepassingsgebied: deze best-practice verhoogt de veiligheid.requested_token_type
Bij token exchange vraagt men standaard een API access token aan voor de opgegeven audience (dus met requested_token_type “urn:ietf:params:oauth:token-type:access_token”). Hierbij ontvangt men een API 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) API 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 API 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 (frontend) toepassing duidelijk dat er een delegatie gebeurt. In dat geval zal een act claim toegevoegd worden aan de claims van het API access token.
Een request zonder actor_token, maakt het voor de API Resource 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 Resource duidelijk dat de actor optreedt in naam van de gebruiker, maar dat de gebruiker niet zelf het request naar de API Resource stuurt. Wanneer de delegatie gebeurt door een (frontend) toepassing, zal voor deze (frontend) toepassing de client_credentials grant toegestaan moeten worden (vraag dit dan aan bij het integratieteam).
De volgende stappen dienen ondernomen worden de (frontend) toepassing. Eerst vraagt de (frontend) toepassing een OIDC access token aan om de gebruiker aan te melden. Daarna moet de (frontend) toepassing via de client credentials grant een API access token aanvragen voor zichzelf 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. Hierdoor bemachtigt de (frontend) toepassing een actor_token. Dit actor_token dient in het request om het token in te wisselen meegegeven te worden in de parameter actor_token.
chaining van actor_tokens
Een API 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 (frontend) toepassing en de API Resource, de autorisatie van de gebruiker voor het gebruik van de API Resource en toekenning van de juiste scopes gelden voor iedere stap in deze ketting.
Authenticatie en meesturen OIDC access token
De (frontend) toepassing dient zich te authenticeren zodat
- De OP kan valideren dat het subject token werd uitgeleverd aan de (frontend) toepassing
- De vertrouwensrelatie tussen de (frontend) toepassing en de audience(s) (API Resource) gevalideerd kan worden
- Het toepassingsgebied van het subject_token niet ongewenst kan uitgebreid worden met het toepassingsgebied van de API Resource
Token exchange is dus niet bruikbaar voor (frontend) toepassing 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 (frontend) toepassing bezorgd. Deze ClientID en Secret kunnen door de (frontend) toepassing 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=openid
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=openid
Client authenticatie via een JWT token
In dit geval genereert de (frontend) toepassing bij de onboarding een asymmetrisch keypaar en bezorgt de Authorization Server het publieke deel ervan: het private deel wordt enkel lokaal op de (frontend) toepassing 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=openid&
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 van de (frontend) toepassing te bevatten |
sub (subject) | VERPLICHT | Deze dient de ClientID van de (frontend) toepassing 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 |