Aanvraag Token Exchange

De (frontend) toepassing vraagt de Token Exchange aan (wissel van OIDC access token naar API access token) en authenticeert zich hiervoor

De (frontend) toepassing initieert een token exchange verzoek richting het Token Endpoint (zie het Discovery Endpoint).

oAuth token exchange - aanvraag

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).

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.

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).

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.

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

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