Blauwe Knop Connect

Overheidsbrede Standaard
Werkversie

Laatst gepubliceerde versie:
https://vorijk.nl/standaard/
Vorige versie:
https://vorijk.nl/standaard/
Redacteur:
Team Vorderingenoverzicht Rijk (Centraal Justitieel Incasso Bureau)
Auteur:
Team Vorderingenoverzicht Rijk (Centraal Justitieel Incasso Bureau), Contact

Samenvatting

Deze Blauwe Knop Connect (BK Connect) standaard beschrijft hoe burgers (op gestandaardiseerde wijze) diensten kunnen gebruiken bij overheidsorganisaties. De basis van de standaard is de Blauwe Knop Connect specificatie. Blauwe Knop Connect bevat alle protocollen die nodig zijn voor het veilig leggen en gebruiken van verbindingen tussen burgers en overheidsorganisaties. Via deze verbindingen kunnen diensten worden aangeroepen. De standaard bestaat uit algemene afspraken die voor allerlei soorten diensten toepasbaar zijn. Daarnaast kan elke concrete dienst ook in een Dienstprofiel specifieke afspraken toevoegen of concretiseren.

Status van dit document

Dit is een werkversie die op elk moment kan worden gewijzigd, verwijderd of vervangen door andere documenten. Het is geen goedgekeurde consultatieversie.

1. Introductie

1.1 Aanleiding

Ontwikkeling van digitale dienstverlening vereist een manier waarop burgers eenvoudig, veilig en vertrouwd zaken kunnen doen met overheden. In het bijzonder in gevallen waar voor het oplossen van een specifiek probleem of het uitvoeren van een specifieke taak gegevens van meerdere organisaties moeten worden gecombineerd en/of communicatie met meerdere organisaties dient plaats te vinden (ketendiensten), is het belangrijk om diensten juist te ontwerpen zodat publieke waarden geborgd zijn en geen ongewenste neveneffecten ontstaan van de dienstverlening. Het verzamelen van dergelijke gegevens (of metadata) bij een derde partij leidt vrijwel direct tot ondermijning van de eigen rechtspositie van burgers. Met behulp van Blauwe Knop Connect kunnen burgers zélf eenvoudig zaken doen met meerdere organisaties, net zoals zij dat in de fysieke leefwereld ook konden, maar dan ondersteund door digitale hulpmiddelen.

Voorbeelden van dergelijke (typen) ketendiensten zijn:

1.2 Blauwe Knop Connect

Met Blauwe Knop Connect kunnen organisaties diensten op betrouwbare wijze aan burgers aanbieden, en kunnen burgers deze diensten op betrouwbare en veilige wijze gebruiken.

Het basisprincipe van Blauwe Knop Connect is dat een burger een gestandaardiseerd (informatie)verzoek verstuurt naar een (overheids)organisatie, en als antwoord ook weer een gestandaardiseerd (informatie)document terug ontvangt van de betreffende organisatie.

Het Blauwe Knop Connect protocol is ontworpen met het doel dat burgers en (overheids)organisaties elk hun wettelijke rechten, taken en plichten effectief en zelfstandig kunnen uitvoeren, waarbij de rechtspositie van elke partij maximaal geborgd is:

Hoewel het Blauwe Knop protocol ontwikkeld is om de kansen die automatisering biedt maximaal te benutten, is het basisprincipe (het uitwisselen van documenten) zo eenvoudig, dat het ook op papier uitgevoerd kan worden. Dit basisprincipe fungeert als een toetssteen waarmee bewaakt wordt dat zo min mogelijk onnodige complexiteit geïntroduceerd wordt. Daardoor blijft het Blauwe Knop protocol eenvoudig te begrijpen, wat bijdraagt aan de robuustheid en het vertrouwen dat gebruikers erin stellen.

1.3 Terminologie

2. Architectuur

2.1 Doelen

De Blauwe Knop Connect standaard beschrijft hoe organisaties diensten kunnen aanbieden aan natuurlijke personen, zodat die personen (gebruikers, burgers) die diensten makkelijk, veilig en efficiënt kunnen gebruiken om een bepaalde taak uit te voeren.

2.1.1 Eenvoudig

Het aanbieden en gebruiken van diensten moet gebruikersvriendelijk en in de praktijk eenvoudig zijn voor aanbieder en gebruiker. Daarom is Blauwe Knop Connect ontworpen vanuit de principes van Gebruiker Centraal.

  • Voor organisaties betekent dit: lage beheerlast, eenvoudig (niet ingewikkeld) uitvoerbaar en integreerbaar.
  • Voor gebruikers betekent dit: maakt goede UX mogelijk, begrijpelijk en uitlegbaar, waardevol in de praktijk.

2.1.2 Veilig

Het aanbieden en gebruiken van diensten moet veilig zijn voor aanbieder en gebruiker, en de informatieveiligheid moet op elk moment maximaal geborgd zijn. Daarom is Blauwe Knop Connect ontworpen vanuit de principes van Security en Privacy by Design.

  • Voor organisaties betekent dat: voldoen aan veiligheidseisen en best practices informatiebeveiliging.
  • Voor gebruikers betekent dit: met aandacht voor publieke waarden, de rechtspositie en informatiepositie van de burger, en privacy en informatiebeveiliging geborgd.

2.1.3 Efficiënt

Het aanbieden en gebruiken van diensten moet efficiënt zijn voor de aanbieder en gebruiker. Dat betekent dat de meerwaarde van technologie benut wordt voor zover aanbieders en gebruikers dat willen.

  • Voor organisaties betekent dit: de standaard stimuleert dat technologie organisaties helpt om verzoeken efficiënt te ontvangen en af te handelen.
  • Voor gebruikers betekent dit: de standaard stimuleert dat technologie burgers helpt om verzoeken efficiënt te versturen, en resultaten te ontvangen en te gebruiken.

2.2 Functies

Deze sectie beschrijft de hoofdfuncties van het Blauwe Knop Connect protocol. Dit zijn de verschillende manieren waarop het protocol kan worden toegepast om concrete dienstverlening te realiseren. Elke functie representeert een specifiek gebruiksscenario of -aspect waarbij organisaties en burgers interacteren volgens de principes van Blauwe Knop Connect.

De functies bouwen voort op elkaar: van het basisprincipe van individuele dienstverlening tot complexe samengestelde ketendiensten die meerdere organisaties betrekken. Elk scenario heeft zijn eigen architectuurvereisten die waarborgen dat de doelen van eenvoud, veiligheid en efficiëntie worden gerealiseerd.

2.2.1 Diensten aanbieden en afnemen (basisprincipe)

Een organisatie biedt een dienst aan die door een burger wordt afgenomen. Om de dienst te gebruiken, stuurt de burger een verzoek naar een de organisatie. De organisatie ontvangt het verzoek, stelt een antwoord op, en stuurt het antwoord direct terug naar de burger. Als het opstellen van een antwoord enige tijd kost, kan de organisatie in plaats van het daadwerkelijke antwoord op het verzoek, ook een antwoord geven dat aangeeft hoe een burger de status van de afhandeling van het verzoek kan volgen. De inrichting hiervan kan voor specifieke diensten zelf worden bepaald.

Diensten aanbieden en afnemen
Figuur 1 Diensten aanbieden en afnemen

Basisprincipe: Het basisprincipe van Blauwe Knop Connect is dat een burger een gestandaardiseerd verzoek voor informatie verstuurt naar een organisatie, en als antwoord ook weer een gestandaardiseerd informatiedocument terug ontvangt van de betreffende organisatie.

Voorbeeld (Vorderingenoverzicht Rijk): een gebruiker dient een verzoek in bij een organisatie om een overzicht te verkrijgen van zijn financiële verplichtingen jegens die organisatie, en ontvangt als antwoord het betreffende overzicht.

Architectuurvereisten:

  • De werking MOET van een dienst moet gedocumenteerd zijn in een dienstenspecificatie die beschrijft welke verzoeken kunnen worden gedaan, en welke antwoorden kunnen worden terugverwacht.
  • Voor een digitale dienst MOET deze dienst een API zijn die voorzien is van een OpenAPI3 specificatie.

2.2.2 Meerdere diensten combineren om een taak uit te voeren (ketendienst)

Bij veel maatschappelijke uitdagingen is het zo dat om een bepaalde taak uit te voeren er een combinatie van meerdere diensten beschikbaar dient te zijn. Informatie uit verschillende diensten wordt bijvoorbeeld door de gebruiker gecombineerd om op basis van persoonlijke omstandigheden de juiste vervolgactie te ondernemen (die actie op zichzelf kan ook weer een dienst zijn). De benodigde combinatie van diensten vormen samen een ketendienst. Het is mogelijk dat diensten een rol spelen in meerdere ketendiensten. De precieze werking van een specifieke ketendienst wordt beschreven in een toepassingsprofiel.

Meerdere diensten combineren
Figuur 2 Meerdere diensten combineren

Voorbeeld (Vorderingenoverzicht Rijk): een gebruiker spreekt bij meerdere (bijvoorbeeld drie) organisaties een informatiedienst aan (informatie over financiële verplichtingen opvragen) om één totaaloverzicht te verkrijgen van financiële verplichtingen. Daarna spreekt de gebruiker bij een vierde organisaties een andere dienst aan om een regeling (bijvoorbeeld een overheidsbrede betalingsregeling) aan te vragen op basis van de eerder opgehaalde informatie.

Architectuurvereisten:

  • Voor een ketendienst MOET toepassingsprofiel worden opgesteld waarin aspecten waar de Blauwe Knop Connect keuzevrijheid laat (zoals de gebruikte implementatievariant of de structuur van het stelseldocument voor de betreffende ketendienst) worden ingevuld. In het toepassingsprofiel moet tenminste gespeficieerd worden welke specifieke onderliggende diensten door welke partijen geleverd moeten worden om de samengestelde ketendienst te laten werken.
  • Het toepassingsprofiel voor de ketendienst MOET alle aanvullende standaarden voor en afspraken over de werking van de specifieke ketendienst documenteren.

2.2.3 Diensten vinden die nodig zijn voor een ketendienst (stelseldocument)

Om een samengestelde dienst (ketendienst) te laten werken, moeten de achterliggende specifieke diensten vindbaar zijn voor gebruikers. Voor het beheren van informatie en afspraken voer de werking van een ketendienst, zoals de vindbaarheid van organisaties die er bij betrokken zijn, kan voor een ketendienst een centraal beheerd stelseldocument worden ingezet. Bij het ontwerpen van een ketendienst is er behoorlijk veel flexibiliteit voor de inhoud en structuur van het stelseldocument voor de betreffende ketendienst. Zo kan de inrichting hiervan passend gemaakt worden bij de gebruikscontext(en) waarvoor de dienst wordt ontworpen. De structuur en werking van het stelseldocument voor een ketendienst moet beschreven worden in het toepassingsprofiel voor de betreffende ketendienst. Indien in het dienstprofiel een stelseldocument wordt beschreven moet bij de uitvoering van de ketendienst een beheerder voor het stelseldocument worden aangewezen (stelselbeheerder).

Diensten vinden behorend bij een ketendienst
Figuur 3 Diensten vinden behorend bij een ketendienst

Voorbeeld (Vorderingenoverzicht Rijk): voor de ketendienst Vorderingenoverzicht Rijk wordt een stelseldocument beheerd door een stelselbeheerder. In het stelseldocument zijn alle deelnemende organisaties opgenomen. Zo kunnen gebruikers de voor hen benodigde diensten vinden om de ketendienst te gebruiken.

Architectuurvereisten:

  • Een ketendienst MAG een lijst van voor een ketendienst relevante diensten publiceren in een stelseldocument.
  • Het stelseldocument MOET een beheerder hebben (stelselbeheerder).
  • Het stelseldocument MOET op een publieke locatie beschikbaar worden gesteld.
  • Het stelseldocument MOET door de stelselbeheerder ondertekend worden.
  • Organisaties en gebruikers MOETEN de handtekening van de stelselbeheerder controleren voordat ze het stelseldocument gebruiken.
  • De stelselbeheerder MAG eisen stellen voor deelname aan de ketendienst.
  • De stelselbeheerder MOET gestelde eisen handhaven/controleren.
  • De stelselbeheerder MOET kwaliteitsmeting uitvoeren van diensten in het stelsel.
  • Een dienstaanbieder MOET meewerking verlenen aan kwaliteitsmeting in het stelsel.

2.2.4 Diensten vinden bij een organisatie (vindbaarheidsconfiguratie)

Om bij een organisatie diensten te kunnen gebruiken, moet het bij gebruikers bekend zijn waar zij deze diensten kunnen gebruiken. Een organisatie moet dus vindbaarheidsconfiguratie publiceren. Bovendien moet bij gebruikers bekend zijn hoe zij een specifieke dienst kunnen gebruiken. Voor elke dienst moet er een specificatie zijn die beschrijft hoe de dienst werkt.

Diensten vinden bij een organisatie
Figuur 4 Diensten vinden bij een organisatie

Voorbeeld (Vorderingenoverzicht Rijk): een gebruiker haalt het stelseldocument van Vorderingenoverzicht Rijk op bij de stelselbeheerder. Het stelseldocument bevat onder andere de url van de vindbaarheidsconfiguratie van elke organisatie die deelneemt aan Vorderingenoverzicht Rijk. De gebruiker haalt met behulp van die informatie vervolgens de vindbaarheidsconfiguratie op bij elke organisatie, waaruit duidelijk wordt welke (versies van) diensten elke organisatie levert en waar deze kunnen worden aangeroepen. Deze informatie wordt vervolgens gebruikt om de speficieke dienst voor het opvragen van informatie over financiële verplichtingen aan de betreffende organisatie (citizen-financial-claims-process) af te nemen.

Architectuurvereisten:

  • Een organisatie die diensten aanbiedt op basis van Blauwe Knop Connect MOET een actuele lijst van de diensten die door de betreffende organisatie worden aangeboden publiek beschikbaar stellen.
  • Voor elke aangeboden dienst, MOET de aanbiedende organisatie het versienummer en de specificatie van de dienst opnemen in de vindbaarheidsconfiguratie.
  • Voor elke aangeboden dienst, MOET de aanbiedende organisatie de locatie van de aangeboden dienst opnemen in de vindbaarheidsconfiguratie.

2.2.5 Hulpmiddelen bij het gebruiken van diensten (technieken en tools)

Ketendiensten stellen bijna altijd gebruikersvriendelijke hulpmiddelen ter beschikking aan gebruikers zodat de ketendienst gemakkelijk en efficiënt te gebruiken is. Een hulpmiddel is software in de vorm van bijvoorbeeld een app, die de gebruiker ondersteunt tijdens het gebruik van een ketendienst. Het hulpmiddel helpt de gebruiker om handelingen in de juiste volgorde worden uit te voeren, de mogelijkheden van de ketendienst toegankelijk en begrijpbaar te maken, en/of door het automatiseren van handelingen. Het gebruik van hulpmiddelen maakt het mogelijk de balans te bewaken tussen eigen controle/autonomie van gebruikers en de zorgplicht/wens om het voor gebruikers gemakkelijk te maken om een ketendienst te gebruiken.

Een hulpmiddel gebruiken
Figuur 5 Een hulpmiddel gebruiken

Voorbeeld (Vorderingenoverzicht Rijk): De Vorderingenoverzicht Rijk applicatie is een voorbeeld van een hulpmiddel die een flink deel van de handelingen automatiseert die nodig zijn om voor een burger een overzicht samen te stellen van hun financiele verplichtingen bij overheidsorganisaties. De applicatie verbindt met de verschillende organisaties in de keten, verzamelt de gegevens en presenteert deze op een begrijpbare manier.

Architectuurvereisten:

  • Een hulpmiddel MOET ontworpen zijn zodat het makkelijk bruikbaar en waardevol is voor gebruikers (bijvoorbeeld op basis van user centered design, of de principes van Gebruiker Centraal).
  • Een hulpmiddel MOET zelfstandig door burgers kunnen worden gebruikt.
  • De werking van hulpmiddelen MOET transparant inzichtelijk zijn. Voor software betekent dit dat de broncode van het hulpmiddel onder een open source licentie beschikbaar moet worden gesteld.
  • Een leverancier van een hulpmiddel MAG NIET gegevens verwerken van of over de gebruiker van het hulpmiddel.
  • Een leverancier van een hulpmiddel MAG NIET volgen en/of bijhouden wat een burger met een hulpmiddel doet.
  • Een leverancier van een hulpmiddel MAG NIET uitvoerend betrokken zijn bij het gebruik van een hulpmiddel.
  • Een leverancier van een hulpmiddel MAG gebruikers leren hoe zij het hulpmiddel op de juiste wijze kunnen gebruiken.

2.2.6 Veilig diensten gebruiken (geauthenticeerde communicatie)

Blauwe Knop Connect is ontworpen volgens de principes van security by design om de veiligheid (beschikbaarheid, integriteit, confidentialiteit) van gegevens te waarborgen bij het gebruiken van diensten. Blauwe Knop Connect stelt eisen aan zowel organisatie als gebruiker op het gebied van communicatie en authenticatie. Diensten kunnen vervolgens vertrouwen op deze veiligheidsaspecten en kunnen daardor zelf eenvoudiger blijven.

2.2.6.1 Communicatie

Communicatie bij het afnemen van diensten dient plaats te vinden via een kanaal dat de veiligheid waarborgt. Dit kanaal kan per dienst verschillen. Het Blauwe Knop protocol is bruikbaar over elke transportlaag die deze vereisten kan invullen.

Enkele voorbeelden zijn:

Publiek internet: met gebruik van TLS (HTTPS)
Publiek internet: met gebruik van tweezijdig TLS (mTLS)
Directe communicatie op locatie (bezorgen van berichten ter adres van de wederpartij)
Postdienst (bewaking van briefgeheim)

Diensten kunnen zelf aanvullende maatregelen nemen om de veiligheid verder te vergroten. Bijvoorbeeld extra versleuteling, dataminimalisatie of andere vormen van bescherming.

2.2.6.2 Authenticatie

Authenticatie bestaat over het algemeen uit twee stappen:

  1. Partij A levert controleerbaar bewijs aan partij B (presentatie, vaak ook identificatie genoemd)
  2. Partij B controleert het bewijs (verificatie)

Voorbeelden van controleerbaar bewijs zijn:

Het tonen van (digitale) certificaten of credentials
Het zetten van een digitale handtekening
Het zetten van een natte handtekening

Het controleren van het bewijs geschiedt op de wijze die past bij het aangeleverde bewijsmateriaal.

Authenticatie: bewijs presenteren en controleren
Figuur 6 Authenticatie: bewijs presenteren en controleren

2.2.6.3 Wederzijdse authenticatie: veilige digitale verbindingen

Veilige digitale verbindingen op basis van Blauwe Knop Connect werken als volgt:

  1. De organisatie kiest een digitaal sleutelpaar.
  2. De organisatie registreert het gekozen sleutelpaar bij de stelselbeheerder.
  3. Het hulpmiddel van de gebruiker kiest een digitaal sleutelpaar.
  1. Bij het verbinden met de organisatie controleert de gebruiker de sleutels van de organisatie (authenticatie #1)
  • Vertrouwen over de juistheid van de sleutels wordt afgeleid uit het stelseldocument (of op andere wijze als er geen stelseldocument is).
  1. Bij het accepteren van verbindingen van gebruikers controleert de organisatie de sleutels van de gebruiker (authenticatie #2).
  • Vertrouwen over identiteit van de gebruiker wordt afgeleid uit eventueel aanwezige certificaten.

De partijen zijn nu wederzijds geauthenticeerd.

  • De sleutels worden vervolgens gebruikt om een veilig transportkanaal op te zetten.
2.2.6.4 Resultaat authenticatie beschikbaar voor dienst

Het resultaat van de authenticatie wordt beschikbaar gesteld aan de afgenomen dienst, zodat die erop kan vertrouwen en identiteitsinformatie en/of sleutelparen kan (her)gebruiken voor verdere veiligheidsmaatregelen zoals toegangscontrole tot de specifieke dienst, personalisatie en/of versleuteling.

Architectuurvereisten:

  • De stelselbeheerder MOET de publieke sleutels van deelnemende organisaties opnemen in het stelseldocument.
  • Wanneer gebruik gemaakt wordt van een stelseldocument MOET de gebruiker het stelseldocument raadplegen en de sleutels van deelnemende organisaties gebruiken om verbindingen met die betreffende organisaties te beveiligen (dus alleen verbindingen aangaan met organisaties die deze sleutels gebruiken)
  • De gebruiker MOET bewijslast presenteren aan de organisatie waarmee verbonden wordt.
  • De organisatie MOET de door de gebruiker aangeleverde bewijslast (handtekening, certificaten, credentials) controleren.
  • De organisatie MOET authenticatieresultaten beschikbaar stellen aan de dienst die wordt aangesproken.
  • De dienst MOET identiteitsinformatie (uit de authenticatieresultaten) gebruiken voor toegangscontrole tot de dienst.
  • De dienst MAG identiteitsinformatie (uit de authenticatieresultaten) gebruiken voor het personaliseren van de dienst.
  • De dienst MOET de sleutelinformatie van de gebruiker (uit de authenticatieresultaten) gebruiken voor versleuteling van informatie die digitaal wordt teruggestuurd naar de burger.

2.2.7 Een sleutelpaar van een gebruiker certificeren (hulpmiddelen activeren)

Voor veilige digitale communicatie genereert elk hulpmiddel een uniek cryptografisch sleutelpaar, bestaande uit een private key (geheim gehouden door het hulpmiddel) en een public key (gedeeld met diensten). De private key wordt gebruikt om berichten digitaal te ondertekenen, terwijl de public key door diensten wordt gebruikt om de echtheid van die handtekeningen te verifiëren.

Een dienst moet de public key van het hulpmiddel kunnen vertrouwen voordat succesvol diensten geleverd kunnen worden. Als het sleutelpaar nog niet bekend is, en zekerheid over de identiteit van de gebruiker voor het leveren van de dienst vereist is, is het nodig om extra bewijsmateriaal in de vorm van certificaten en/of credentials aan te leveren bij het opzetten van veilige verbindingen.

De gebruiker kan dit aanvullende bewijsmateriaal verkrijgen via het proces van legaliseren. Tijdens het legaliseren wordt de identiteit van de burger gecontroleerd en wordt het digitale sleutelpaar gekoppeld aan een persoon. Dit is bestaande juridische praktijk genaamd Legaliseren, waarvoor men in de papieren wereld onder meer terecht kan bij gemeenten, notarissen en/of (in het buitenland) bij een Nederlandse ambassade.

Digitaal kan dit op tenminste twee manieren:

  • Certificering met behulp van een wallet
  • Certificering door een derde partij (legalisator)

Digitaal legaliseren
Figuur 7 Digitaal legaliseren

Architectuurvereisten:

  • De stelselbeheerder MOET toegestane legalisatiemethoden opnemen in het stelseldocument
  • De stelselbeheerder MOET vertrouwde legalisators aanwijzen en opnemen in het stelseldocument
  • Een legalisator MOET beheer voeren over toegelaten hulpmiddelen voor specifieke ketendiensten
  • Een legalisator MOET de identiteit van de gebruiker controleren
  • Een legalisator MOET elk door de gebruiker gekozen sleutel certificeren (die aan de vereiste cryptografische specificaties voldoet)
  • Een legalisator MOET aan het einde van het legaliseerproces een certificaat en/of credential verstrekken aan de gebruiker dat gekoppeld is aan de door de gebruiker gekozen sleutel.
  • Een legalisator MOET elke gebruiker inzage geven in gelegaliseerde sleutels en bijbehorende certificaten/credentials.
  • Een legalisator MOET elke gebruiker de mogelijkheid geven certificaten/credentials in te trekken (revocation).
  • Een legalisator MOET certificaten/credentials intrekken indien er gegronde signalen zijn dat sprake is van misbruik (revocation).

2.2.8 Toegang krijgen tot diensten (autorisatie)

Omdat tijdens het verbinden met een dienst volgens Blauwe Knop Connect een gebruiker geauthenticeerd is, kan er bij de afhandeling op worden vertrouwd dat de gebruiker is wie hij zegt dat hij is. De dienst kan dus zelf eenvoudiger blijven, omdat de complexiteit voor het veilig verbinden buiten de dienst wordt gehouden.

Een dienst krijgt toegang tot de informatie die tijdens de authenticatie van de gebruiker gecontroleerd is. Deze informatie kan gebruikt worden bij het bepalen of de dienst mag worden verleend (autorisatie), en tijdens het afhandelen van de dienst (personalisatie). Deze en andere gegevens die worden gebruikt tijdens het afhandelen van de dienst mogen niet gebruikt worden voor andere doeleinden dan het afhandelen van de dienst.

Voorbeeld (Vorderingenoverzicht Rijk): Omdat de dienst waarmee een gebruiker informatie over betalingsverplichting aan een organisatie opvraagt wordt aangesproken via een veilige Blauwe Knop Connect verbinding, kan deze dienst bij de afhandeling (het verwerken van het informatieverzoek) gebruik maken van de tijdens de authenticatie verstrekte identiteitsgegevens (het BSN) om een persoonlijk antwoord op te stellen. Bovendien kan het tijdens het verbinden gebruikte sleutelmateriaal worden gebruikt om het persoonlijke antwoord te versleutelen zodat alleen de betreffende gebruiker het antwoord kan openen.

Een dienst gebruiken via een veilige verbinding
Figuur 8 Een dienst gebruiken via een veilige verbinding

Architectuurvereisten:

  • Een gebruiker MOET een dienst altijd aanroepen via een veilige verbinding.
  • Een gebruiker MOET bij het aanroepen van de dienst een verwijzing naar het authenticatieresultaat (toegangstoken) meesturen.
  • Een organisatie MAG NIET gegevens over de gebruiker van de dienst voor andere doeleinden gebruiken dan het uitvoeren van de dienst.
  • Een dienst MOET controleren of de gebruiker geautoriseerd is voor het gebruik van de dienst.
  • Een dienst MAG de gegevens over de gebruiker van de dienst gebruiken bij de afhandeling van de dienst.

2.3 De standaard in de praktijk brengen (specificaties en (referentie-)implementaties)

De architectuur zoals hier beschreven kan op verschillende manieren in de praktijk worden gebracht. Via verschillende media (fysiek, digitaal, etc.), met verschillende soorten hulpmiddelen (pen en papier, formulieren, hard- en software). De rollen van stelselbeheerder, legalisator en deelnemende gebruikers en organisaties kunnen op verschillende manieren belegd worden (overheden, notarissen, dienstverleners, etc.), maar ook digitaal met toepassing van meer klassieke (OpenID4VP) of moderne standaarden (FSC voor natuurlijke personen). En met gebruik van verschilende wijzen van identiteitscontrole bij deelname van natuurlijke personen aan het stelsel (DigiD, Digitale Identiteit, identiteitscontrole in persoon). In het volgende hoofdstuk worden een aantal van deze implementaties in detail gespecificeerd.

3. Cryptografie

Dit hoofdstuk beschrijft de algemene vereisten rondom cryptografie in Blauwe Knop Connect

3.1 Digitale handekeningen

Voor alle digitale handtekeningen in deze standard MOETEN een van de volgende algoritmes gebruiken:

Merk op dat de Secure Enclave (SE) van iPhones en de Trusted Execution Environment (TEE) van Android telefoons uitsluitend ECDSA op P-256 ondersteunen. Wanneer een private key in een SE/TEE beveiligd dient te worden is dit dan dus de enige optie.

Deze standaard maakt veelvuldig gebruik van JWS (RFC 7515) om digitaal ondertekende datastructuren te encoderen. In het vervolg van deze standaard tonen we een JWS steeds als JSON structuur. Dus gegeven het volgende JWS voorbeeld:

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFt
ZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yt1lkupgb536FyX2_IzrElyQJ7
ep3MJhZ_7w4wpz0GIzWnLkESQ6RDvRmk_HTwTbLsJdLhGLj-7KB_FEvOo8sQ

Schrijven we het volgende:

{
  "alg": "ES256",
  "typ": "JWT"
}
.
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Deze weergave toont niet de handtekening (het laatste deel van de JWS, na de tweede punt). Alle whitespace (spaties en newlines) zijn enkel voor leesbaarheid en dienen te worden verwijderd bij het tekenen van een JWS.

Elk digitaal ondertekend bericht in deze standaard MOET in de vorm van een JWS (RFC 7515) zijn.

3.2 Asymmetrische encryptie

Voor alle asymmetrische encryptie in deze standaard MOET ECIES gebruikt worden (dit heet ECDH-ES in JWEs (RFC 7518)), met de volgende parameters:

NB: Een versleuteld bericht wordt soms verstuurd in de vorm van een JWE. JWS en JWE zijn allebei vormen van een JWT (JSON Web Token, RFC 7519). De term JWT kan naar zowel een JWS als een JWE refereren. In dit document gebruiken we consistent "JWS" of "JWE" om expliciet te zijn.

3.3 Symmetrische encryptie

Voor alle symmetrische encryptie in deze standaard MOET AES gebruikt worden, met als parameters een van de volgende twee:

3.4 JWE headers

Wanneer een bericht wordt versleuteld in de vorm van een JWE, dan geldt voor de headers van die JWE het volgende:

3.5 Transport

Alle verkeer tussen de App en de (infrastructuur van de) Verifier, Dienst, of Credential Issuer MOET gebruik maken van minstens TLS 1.3.

4. Specificaties

4.1 Stelselbeheer

Stelselbeheer is het beheren van een samenhangend systeem van ICT-standaarden, diensten en organisatorische afspraken die effectieve en veilige samengestelde dienstverlening aan burgers mogelijk maakt. Voor ketendiensten waarbij gebruikers met meerdere organisaties moeten interacteren, zorgt stelselbeheer voor service discovery, vertrouwensbeheer, kwaliteitsborging en governance.

4.1.1 Stelseldocument

Een stelseldocument is een centraal beheerd document dat essentiële informatie bevat voor het functioneren van een specifieke ketendienst. Het stelseldocument maakt service discovery mogelijk en ondersteunt vertrouwensbeheer tussen organisaties en gebruikers.

4.1.1.1 Structuur van het Stelseldocument

De vorm en structuur van een stelseldocument kan door de stelselbeheerder zelf worden gekozen. Vaak is het waardevol om in het stelseldocument tenminste op te nemen (1) welke organisaties deelnemen aan de ketendienst, (2) welke partijen vertrouwen leveren in de ketendienst (bijvoorbeeld app managers), en (3) welke documenttypen in de dienst worden gebruikt en ondersteund. Het stelseldocument MAG dus bijvoorbeeld de volgende componenten bevatten:

Organisaties (organizations):

  • oin: Organisatie-identificatienummer (unieke identifier)
  • name: Naam van de organisatie
  • discovery_url: URL naar de vindbaarheidsconfiguratie van de organisatie
  • public_key: Publieke sleutel van de organisatie voor veilige communicatie
  • logo_url: (optioneel) URL naar het logo van de organisatie

App Managers (app_managers):

  • oin: Organisatie-identificatienummer van de app manager
  • name: Naam van de app manager
  • discovery_url: URL naar de vindbaarheidsconfiguratie van de app manager
  • public_key: Publieke sleutel van de app manager

Documenttypen (document_types):

  • name: Naam van het ondersteunde documenttype
4.1.1.2 Technische Vereisten

Voor het Stelseldocument:

  • Het stelseldocument MOET in JSON formaat beschikbaar zijn
  • Het stelseldocument MOET op een publiek toegankelijke locatie worden gepubliceerd
  • Het stelseldocument MOET digitaal ondertekend worden door de stelselbeheerder
  • Het stelseldocument MOET versienummering ondersteunen

Voor Publieke Sleutels:

  • Publieke sleutels MOETEN worden opgenomen voor alle deelnemende organisaties
  • Publieke sleutels MOETEN voldoen aan de cryptografische vereisten uit hoofdstuk Cryptografie
  • Publieke sleutels MOETEN regelmatig worden gevalideerd door de stelselbeheerder

Voor Service Discovery:

  • Elke organisatie MOET een geldige discovery_url hebben
  • Discovery URLs MOETEN verwijzen naar actuele vindbaarheidsconfiguraties
  • Discovery URLs MOETEN via HTTPS toegankelijk zijn

4.1.2 Verantwoordelijkheden van de stelselbeheerder

De stelselbeheerder MOET:

  • Het stelseldocument actueel houden en digitaal ondertekenen
  • Deelname-eisen stellen en handhaven voor organisaties
  • Kwaliteitsmetingen uitvoeren van diensten in het stelsel
  • Publieke sleutels van deelnemende organisaties beheren
  • Vertrouwde legalisatiemethoden en legalisatoren aanwijzen
  • Een publiek toegankelijke API voor het stelseldocument onderhouden

De stelselbeheerder MAG:

  • Aanvullende eisen stellen voor deelname aan de ketendienst
  • Organisaties uitsluiten die niet voldoen aan de gestelde eisen
  • Het stelseldocument uitbreiden met aanvullende metadata

4.1.3 Interactie met het Stelseldocument

Gebruikers MOETEN:

  • Het stelseldocument ophalen voordat een ketendienst wordt gebruikt
  • De digitale handtekening van de stelselbeheerder verifiëren
  • De publieke sleutels uit het stelseldocument gebruiken voor veilige verbindingen
  • Regelmatig controleren op updates van het stelseldocument

Organisaties MOETEN:

  • Hun publieke sleutel registreren bij de stelselbeheerder
  • Hun vindbaarheidsconfiguratie actueel houden
  • Meewerken aan kwaliteitsmetingen
  • Voldoen aan de door de stelselbeheerder gestelde eisen

4.1.4 Voorbeeld Implementatie

Een praktijkvoorbeeld van stelselbeheer is te vinden in de implementatie voor Vorderingenoverzicht Rijk, waarbij:

  • Het stelseldocument alle deelnemende overheidsorganisaties bevat
  • Gebruikers het stelseldocument gebruiken om relevante diensten te ontdekken
  • Veilige verbindingen worden opgezet met behulp van de publieke sleutels uit het stelseldocument
  • Kwaliteit en betrouwbaarheid worden gewaarborgd door centraal beheer

4.2 Vindbaarheidsconfiguratie

Een vindbaarheidsconfiguratie is een JSON-document dat door elke organisatie wordt gepubliceerd om haar beschikbare Blauwe Knop Connect diensten vindbaar te maken voor gebruikers en hulpmiddelen. Dit document specificeert welke diensten beschikbaar zijn, waar deze kunnen worden aangeroepen, en welke versies worden ondersteund.

4.2.1 Doel en Functie

De vindbaarheidsconfiguratie stelt gebruikers en hulpmiddelen in staat om:

  • Beschikbare diensten bij een organisatie te ontdekken
  • De juiste endpoint URLs voor diensten te verkrijgen
  • Ondersteunde API versies te identificeren
  • Organisaties in staat te stellen zelf te beheren welke diensten zij op welk moment aanbieden, zonder dat de stelselbeheerder daar bij betrokken hoeft te worden.

4.2.2 JSON Structuur

De vindbaarheidsconfiguratie MOET een JSON-object zijn met de volgende structuur:

{
  "serviceName1": {
    "v1": "https://service1.v1.organisatie.nl/api",
    "v2": "https://service1.v2.organisatie.nl/api"
  },
  "serviceName2": {
    "v1": "https://service2.v1.organisatie.nl/api",
    "v3": "https://service2.v3.organisatie.nl/api"
  }
}
4.2.2.1 Structuurelementen

Service Namen:

  • De toplevel keys in het JSON-object representeren de namen van beschikbare diensten
  • Service namen MOETEN uniek zijn binnen de vindbaarheidsconfiguratie
  • Service namen MOETEN overeenkomen met de namen van diensten in het relevante dienstprofiel

Versie-identificatie:

  • Elke dienst MOET één of meer versies specificeren
  • Versies MOETEN semantische versienummering volgen (bijv. "v1", "v2", "v2.1")
  • De versie identifier wordt gebruikt als key voor het bijbehorende endpoint

Endpoint URLs:

  • Elke versie van een dienst MOET een volledig gekwalificeerde URL hebben
  • URLs MOETEN het HTTPS protocol gebruiken in productieomgevingen
  • URLs MOETEN verwijzen naar werkende API endpoints

4.2.3 Technische Vereisten

Voor de Vindbaarheidsconfiguratie:

  • Het document MOET in geldig JSON formaat zijn
  • Het document MOET op een publiek toegankelijke HTTPS URL beschikbaar zijn
  • Het document MOET geserveerd worden met de Content-Type: application/json header
  • Het document MOET door de betreffende organisatie up to date worden gehouden

Voor Service Endpoints:

  • Alle endpoint URLs MOETEN volledig gekwalificeerde URLs zijn
  • Endpoints MOETEN bereikbaar zijn via het gespecificeerde protocol
  • Endpoints MOETEN voldoen aan de OpenAPI3 specificatie voor de betreffende dienst
  • Endpoints MOETEN gebruik maken van TLS 1.3 of hoger

Voor Versioning:

  • Organisaties MOETEN backwards compatibility ondersteunen voor tenminste één voorgaande major versie
  • Deprecated versies MOETEN voor een redelijke periode beschikbaar blijven

4.2.4 Publicatie en Toegang

Publicatie:

  • Elke organisatie MOET haar vindbaarheidsconfiguratie publiek publiceren
  • De URL van de vindbaarheidsconfiguratie MOET worden opgenomen in het relevante stelseldocument
  • De configuratie MOET zonder authenticatie toegankelijk zijn voor lezen

Caching en Updates:

  • Clients MOGEN de vindbaarheidsconfiguratie cachen voor verbeterde performance
  • Organisaties MOETEN appropriate HTTP cache headers instellen
  • Bij significante wijzigingen MOETEN organisaties overwegen om cache invalidatie te ondersteunen

4.2.5 Voorbeeld Implementatie

Een praktijkvoorbeeld van een vindbaarheidsconfiguratie:

{
  "financialClaimRequestApi": {
    "v2": "http://financial-claim-request-api.demo.bk-manager.source-organization.rijksoverheid.nl",
    "v4": "http://financial-claim-request-api.demo.bk-manager.source-organization.rijksoverheid.nl"
  },
  "sessionApi": {
    "v2": "http://session-api.demo.bk-manager.source-organization.rijksoverheid.nl"
  }
}

In dit voorbeeld:

  • Twee diensten zijn beschikbaar: financialClaimRequestApi en sessionApi
  • De financialClaimRequestApi ondersteunt zowel versie v2 als v4
  • De sessionApi ondersteunt alleen versie v2
  • Alle endpoints gebruiken een consistent domeinpatroon

4.2.6 Voorbeeld van de integratie van de vindbaarheidsconfiguratie met Stelselbeheer

  1. Het stelseldocument bevat de URL naar elke organisatie's vindbaarheidsconfiguratie
  2. Gebruikers halen eerst het stelseldocument op om deelnemende organisaties te identificeren
  3. Vervolgens wordt de vindbaarheidsconfiguratie van relevante organisaties opgehaald
  4. Ten slotte worden de specifieke dienst-endpoints aangeroepen

Deze architectuur zorgt voor flexibiliteit en schaalbaarheid, waarbij organisaties onafhankelijk hun diensten kunnen beheren terwijl het stelselbeheer de coördinatie tussen organisaties faciliteert.

4.3 Diensten aanbieden via veilige verbindingen

4.3.1 Publiek internet (HTTPS-JWT): CreateSession

Deze sectie beschrijft een protocol waarmee een app aan een verifier kan aantonen dat hij controle heeft over de private key behorende bij een bepaalde public key (sleutelpaar). Dit protocol kan vervolgens gebruikt worden door:

  1. Een uitgever die de public key van de app in een Verifiable Credential stopt en deze vervolgens aan de app uitreikt;
  2. Een verifier, die middels dit protocol en het Verifiable Credential de gebruiker kan authenticeren.

Het protocol levert een sessietoken op voor gebruik in verdere applicatie-specifieke protocollen, en sleutelmateriaal om protocolverkeer te versleutelen.

In hoofdlijnen ziet dit protocol er als volgt uit.

`CreateSession` protocol (beknopte weergave)
Figuur 9 CreateSession protocol (beknopte weergave)

4.3.1.1 Scope

Het protocol in deze sectie is generiek en kan bij verschillende organisaties worden toegepast, voor verschillende en (mogelijk) ongerelateerde toepassingen, zoals beschreven in de sectie over Architectuur en functies. Er zijn daarom dus verschillende domeinen, of scopes, waarin authenticatie plaats moet kunnen vinden. Om ervoor te zorgen dat authenticatie binnen het ene domein niet verward kan worden met authenticatie in het andere domein bevat een Verifiable Credential in dit protocol een scope parameter met een string als waarde.

Een organisatie gebruikt het protocol in deze sectie om een gebruiker te authenticeren teneinde een specifieke dienst aan te kunnen bieden. Het domein van die dienst wordt gerepresenteerd door de scope. De organisatie MOET nadat het protocol in deze sectie is afgerond de scope uit het Verifiable Credential vergelijken met de scope die hij verwacht, en afbreken als die niet overeenkomen.

De App MAG meerdere Verifiable Credentials hebben met verschillende waardes voor de scope parameter, zodat hij zich kan authenticeren in verschillende toepassingen. De App moet voordat het protocol in deze sectie begint weten welke scope de Verifier verwacht.

4.3.1.2 Verifiable Credentials en Presentations
4.3.1.2.1 Verifiable Credentials

Het Verifiable Credential die de App ontvangt van de App Manager en tijdens authenticatie richting de Verifier presenteert MOET een JWS zijn, met daarin de volgende velden (claims):

Claim Name Claim Description
app_public_key Public key van de burger in DER formaat, Base64-encoded
scope Scope (zie "Scope" sectie hierboven)
iss Organisatie-identificatienummer van de app manager
iat (Issued At) Moment van uitgifte (Unix timestamp)
nbf (Not Before) Begindatum van geldigheid (Unix timestamp)
exp (Expiry) Verloopdatum (Unix timestamp)
bsn Burgerservicenummer
given_name Voornaam/voornamen
family_name Achternaam/achternamen

Hierin zijn alle drieletterige claims behalve bsn gestandaardiseerd in het IANA "JSON Web Token Claims" register.

De JWS MAG een kid veld in de header bevatten die de public key van de App Manager identificeert waarmee de JWS geverifieerd kan worden. Volgens RFC7515 (JWS) MOET de kid een string zijn. Samen met het iss veld kan de App Manager public key worden opgezocht middels een proces dat kan verschillen per scope (zie de "App manager public key lookup" sectie hieronder).

Voorbeeld:

{
  "typ": "jwt",
  "alg": "ES256",
  "kid": "1"
}
.
{
  "app_public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0Ejs8jmnIjkb+wMpaQugg6VY6j7bpgYQYGTt7Ji/RhSJvQKT9Q63RsfD0XtdIlgosZkV70ocwbYhL8HadgVulQ==",
  "scope": "nl.vorijk.oauth_scope.blauwe_knop",
  "iss": "00000001234567890000", // OIN
  "iat": 1704063600,
  "nbf": 1704063600,
  "exp": 1735686000,
  "bsn": "999991772",
  "given_name": "Willeke Liselotte",
  "family_name": "De Bruijn"
}
4.3.1.2.2 Verifiable Presentation

Voordat de App zich authenticeert aan een Verifier MOET hij controleren dat het Verifiable Credential volgens de timestamp in het exp veld niet verlopen is, of gaat verlopen binnen één minuut. Als dat wel zo is, dan MOET de App het Verifiable Credential eerst verversen voordat hij aan het protocol begint.

Tijdens authenticatie ondertekent de App met diens private key een willekeurige string, genaamd de nonce, die gegenereerd is door de Verifier. Dit resulteert in een JWS waarin de volgende claims MOETEN staan:

Claim naam Claim beschrijving
sub String die de waarde "challenge_response" MOET hebben
aud OIN van de Verifier waar de App naar authenticeert
nonce Willekeurige string gegenereerd door de Verifier

Voorbeeld:

{
  "typ": "jwt",
  "alg": "ES256",
}
.
{
  "sub": "challenge_response",
  "aud": "00000001234567890001",
  "nonce": "L9E4aGM9ZzhhC7WLVxa1XKOzie7bzKh0"
}

Vervolgens maakt de App een Verifiable Presentation. Dit is een JSON object met daarin de volgende velden:

Naam Beschrijving
app_nonce_signature Bovenstaande JWS
certificate_type MOET zijn ofwel "app_manager_jwt_certificate" ofwel "certificate_type_self_signed"
certificate Het Verifiable Credential als certificate_type gelijk is aan "app_manager_jwt_certificate"; of een self-signed JWT (zie hieronder) met daarin de app public key als certificate_type gelijk is aan "certificate_type_self_signed"
session_aes_key AES key (Base64-encoded) voor versleuteling van verder verkeer

Het certificate_type met waarde certificate_type_self_signed is bedoeld om het opzetten van veilige verbindingen mogelijk te maken wanneer nog geen identiteitsinformatie is uitgewisseld. Partijen weten dan dus wél dat zij veilig zaken met elkaar doen, maar nog niet met wie. Dit is bijvoorbeeld het geval in het proces van uitgifte van een certificaat door een app manager, vóórdat er identiteitscontrole heeft plaatsgevonden (met een inlogmiddel zoals DigiD).

Het certificate_type met waarde app_manager_jwt_certificate is bedoeld om het opzetten van veilige verbindingen mogelijk te maken wanneer er een certificaat uitgegeven door een app manager wordt gebruikt.

Als certificate_type gelijk is aan certificate_type_self_signed, dan MOET het certificate veld een JWS hebben van de volgende vorm:

{
  "typ": "jwt",
  "alg": "ES256",
}
.
{
  "app_public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE16YiVsBE1K+I5iksaBbkc1Evfk6/0wPSO3Rwni1HVqOcmy5Hjr61/arQxibswOj+v/8uBCA/AzMFVvqFOI96Vg==",
  "sub": "certificate_type_self_signed"
}

Deze JWS MOET getekend zijn met de private key waarvan de public key in het app_public_key veld staat, en de JWS in het app_nonce_signature MOET ook met deze private key getekend zijn.

Voorbeelden van Verifiable Presentations:

  • Als certificate_type gelijk is aan app_manager_jwt_certificate:
    {
      "app_nonce_signature": "eyJ0eXAiOiJqd3QiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJjaGFsbGVuZ2VfcmVzcG9uc2UiLCJhdWQiOiIwMDAwMDAwMTIzNDU2Nzg5MDAwMSIsIm5vbmNlIjoiTDlFNGFHTTlaemhoQzdXTFZ4YTFYS096aWU3YnpLaDAifQ.1TtHJXzBS3OGZzMKcalw5qoQb8H-WAwTIeOIWROM0hCDxKRKQdQyz_jESVycQSwnk9Ldgv87_e9KZr4SkOh_NQ",
      "certificate_type": "app_manager_jwt_certificate",
      "certificate": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBfcHVibGljX2tleSI6Ik1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTE2WWlWc0JFMUsrSTVpa3NhQmJrYzFFdmZrNi8wd1BTTzNSd25pMUhWcU9jbXk1SGpyNjEvYXJReGlic3dPait2Lzh1QkNBL0F6TUZWdnFGT0k5NlZnPT0iLCJzY29wZSI6Im5sLnZvcmlqay5vYXV0aF9zY29wZS5ibGF1d2Vfa25vcCIsImlzcyI6IjAwMDAwMDAxMjM0NTY3ODkwMDAwIiwiaWF0IjoxNzA0MDYzNjAwLCJuYmYiOjE3MDQwNjM2MDAsImV4cCI6MTczNTY4NjAwMCwiYnNuIjoiOTk5OTkxNzcyIiwiZ2l2ZW5fbmFtZSI6IldpbGxla2UgTGlzZWxvdHRlIiwiZmFtaWx5X25hbWUiOiJEZSBCcnVpam4ifQ.3r49YRPFBj6imBBMJHH9NHS-G9WZW6omC78wFlqC8Z3vV7TnKzdQBc3b3_2P6TgqwAjB4gZs9Gd-NNijygkv3w",
      "session_aes_key": "/YyG+FNLinwQqZFgGUribQ=="
    }
    
  • Als certificate_type gelijk is aan certificate_type_self_signed:
    {
      "app_nonce_signature": "eyJ0eXAiOiJqd3QiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJjaGFsbGVuZ2VfcmVzcG9uc2UiLCJhdWQiOiIwMDAwMDAwMTIzNDU2Nzg5MDAwMSIsIm5vbmNlIjoiTDlFNGFHTTlaemhoQzdXTFZ4YTFYS096aWU3YnpLaDAifQ.1TtHJXzBS3OGZzMKcalw5qoQb8H-WAwTIeOIWROM0hCDxKRKQdQyz_jESVycQSwnk9Ldgv87_e9KZr4SkOh_NQ",
      "certificate_type": "certificate_type_self_signed",
      "certificate": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBfcHVibGljX2tleSI6Ik1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTE2WWlWc0JFMUsrSTVpa3NhQmJrYzFFdmZrNi8wd1BTTzNSd25pMUhWcU9jbXk1SGpyNjEvYXJReGlic3dPait2Lzh1QkNBL0F6TUZWdnFGT0k5NlZnPT0iLCJzdWIiOiJjZXJ0aWZpY2F0ZV90eXBlX3NlbGZfc2lnbmVkIn0.N5ukfBIFd-17vx8I5SszixkZGW4Ay4Zq2-e1eXqmJ5l-kIC_TVWmc5b72-SB5e7yER2Kaq1GS3g4SFQjD9LuVA",
      "session_aes_key": "/YyG+FNLinwQqZFgGUribQ=="
    }
    

De Verifier MOET de volgende stappen uitvoeren bij het verifiëren van de Verifiable Presentation:

  1. Controleer dat de Verifiable Presentation een JSON object is met daarin de velden zoals benoemd in de tabel over de Verifiable Presentation structuur hierboven.
  2. Controleer dat de session_aes_key in de Verifiable Presentation bestaat uit 16 bytes na Base64 decoding.
  3. Controleer dat het certificate veld een string is van de vorm van een JWS, en parse de header en body van de JWS (nog zonder de JWS te verifiëren).
  4. Controleer dat certificate_type in de Verifiable Presentation een van de volgende twee waardes bevat.
    1. "certificate_type_self_signed". Verifieer in dit geval de JWS in het certificate veld als volgt:
      1. Controleer dat de body van de JWS een app_public_key veld bevat, met daarin een Base64-encoded DER-encoded EC public key van een ondersteund algoritme en curve die geldig is (de coördinaten refereren naar een bestaand element van de elliptic curve).
      2. Verifieer de JWS tegen deze public key.
      3. Controleer dat de JWS een sub veld met waarde "certificate_type_self_signed" bevat.
    2. "app_manager_jwt_certificate". Verifieer in dit geval de JWS in het certificate veld als volgt:
      1. Gegeven het kid veld uit de header (indien aanwezig), en de iss en scope velden uit de body, zoek de public key van de app manager op. (Dit proces kan verschillen per scope, zie de "App manager public key lookup" sectie hieronder.)
      2. Gegeven de public key van de app manager, verifieer het certificate veld als JWS. Controleer hierbij ook de nbf en exp velden als in § 4.1 van RFC 7519.
      3. Controleer dat de JWS de velden uit de Verifiable Credentials sectie bevat, en dat die van het juiste JSON datatypes zijn.
      4. Voor gebruik in de volgende stap, parse het app_public_key veld uit de JWS als Base64-encoded DER-encoded EC public key, en controleer dat hij van een ondersteund algoritme en curve is en dat hij geldig is (de coördinaten refereren naar een bestaand element van de elliptic curve).
  5. Verifieer dat de app_nonce_signature in de Verifiable Presentation een geldige JWS is ten opzichte van de geparseerde app_public_key uit de JWS van de vorige stap, met als claims:
    • sub met als vaste waarde challenge_response,
    • de OIN van de Verifier in het aud veld,
    • de nonce die de Verifier eerder naar de App heeft gestuurd.

De bsn, given_name, en family_name velden uit het Verifiable Credential (in het geval van app_manager_jwt_certificate) of de app_public_key uit het certificate (in het geval van certificate_type_self_signed) zijn nu gevalideerd en klaar voor gebruik.

4.3.1.3 App manager public key lookup

Apps en organisaties moeten de public key van de App Manager (de uitgever van het Verifiable Credential) kunnen opzoeken, waarmee het Verifiable Credential kan worden geverifieerd. Hoe dit gedaan moet worden verschilt per scope.

Voor wanneer de scope gelijk is aan nl.vorijk.oauth_scope.blauwe_knop staat hier gespecificeerd hoe dit proces gaat.

4.3.1.4 Protocolbeschrijving
4.3.1.4.1 Sequence diagram
4.3.1.4.1.1 JWS/JWT Berichten in het CreateSession Protocol

De verschillende typen berichten in dit protocol zijn:

  • App Manager Certificate JWT: Het Verifiable Credential uitgegeven door de App Manager (beschreven in sectie Verifiable Credentials)
  • Challenge Response JWT: De JWS waarin de App de nonce ondertekent (beschreven in sectie Verifiable Presentation)
  • Self-Signed Certificate JWT: De zelf-ondertekende JWS gebruikt wanneer nog geen identiteitsinformatie is uitgewisseld

Het CreateSession protocol ziet er in een sequence diagram als volgt uit:

`CreateSession` protocol
Figuur 10 CreateSession protocol

4.3.1.4.1.2 Terminologie in Sequence Diagrams

In de sequence diagrams worden de volgende termen gebruikt:

  • EC (Elliptic Curve): Verwijst naar elliptic curve cryptografie, zoals gespecificeerd in de cryptografie sectie. Alle sleutelparen in het protocol gebruiken elliptic curve algoritmen.
  • Root keypair: Het hoofdsleutelpaar van een organisatie of app, dat wordt gebruikt voor langdurige identificatie en wordt geregistreerd bij de stelselbeheerder.
  • Ephemeral keypair: Een tijdelijk sleutelpaar dat wordt gegenereerd voor een specifieke sessie en na gebruik wordt weggegooid. Dit biedt forward secrecy - oude communicatie blijft veilig zelfs als het root keypair wordt gecompromitteerd.
4.3.1.4.2 Protocolberichten

Er volgt een expliciete beschrijving van de protocolberichten, die refereert aan de genummerde stappen in bovenstaand sequence diagram. Alle whitespace in JSON structuren is enkel bedoeld voor de leesbaarheid van deze standaard en dient niet te worden opgenomen in implementaties.

4.3.1.4.2.1 Stap 1

De App initieert het CreateSession protocol door een sessie-aanvraag te sturen naar de Verifier.

4.3.1.4.2.2 Stap 2

De App vraagt een nieuwe challenge op met een HTTP POST request zonder body naar /v1/challenge.

4.3.1.4.2.3 Stap 4

De Verifier genereert met een cryptographically secure pseudorandom number generator (CSPRNG) een nonce bestaande uit minimaal 16 willekeurige bytes.

4.3.1.4.2.4 Stap 9

De Verifier antwoordt op het HTTP request van de App uit stap 2 met een JWS, ondertekend met zijn private key, en met de volgende claims:

  • sub: een string die de waarde "challenge" MOET hebben.
  • nonce: de nonce uit Stap 4, Base64-encoded.
  • ephemeral_organization_ec_public_key: de Base64-encoding van de DER-encoded public key van de verifier.

De JWS MAG een kid header gebruiken om de public key aan te duiden waarmee de JWS geverifieerd moet worden.

Voorbeeld:

{
  "typ": "jwt",
  "alg": "ES256",
  "kid": "1"
}
.
{
  "sub": "challenge",
  "nonce": "BZpwbYf2TIYxvJEQY2FtAg==",
  "ephemeral_organization_ec_public_key": "MFkw....Wzhw=="
}
4.3.1.4.2.5 Stap 10 t/m 12

De App:

  • Controleert dat de root organization EC public key van een ondersteund algoritme en curve is en dat hij geldig is (de coördinaten refereren naar een bestaand element van de elliptic curve).
  • Verifieert de JWS van de Verifier uit bovenstaande stap met de root organization EC public key.
  • Controleert dat de JWS een sub veld met waarde challenge bevat.
  • Controleert dat de ephemeral organization EC public key van een ondersteund algoritme en curve is en dat hij geldig is.
4.3.1.4.2.6 Stap 13

De App genereert met een CSPRNG een nieuwe willekeurige AES key van de juiste grootte (128 bits in het geval van AES128 en 256 bits in het geval van AES256).

4.3.1.4.2.7 Stap 14 t/m 19

De App maakt het Verifiable Presentation als in de "Verifiable Presentation" sectie hierboven, en versleutelt deze middels ECDH-ES in de vorm van een JWE naar de ephemeral organization EC public key van de Verifier.

4.3.1.4.2.8 Stap 20

De App stuurt middels een HTTP POST naar /v1/complete het volgende JSON object naar de Verifier:

  • nonce: de nonce die de Verifier eerder aanleverde.
  • encrypted_challenge_result: de Verifiable Presentation JWE uit de vorige stap.

Voorbeeld:

{
    "nonce": "BZpwbYf2TIYxvJEQY2FtAg==",
    "encrypted_challenge_result": "eyBLyPjsJZs...5Y2tNYLRui"
}
4.3.1.4.2.9 Stap 25

De Verifier MOET de Verifiable Presentation verifiëren als in de "Verifiable Presentation" sectie hierboven.

4.3.1.4.2.10 Stap 26

De Verifier genereert met een CSPRNG een willekeurige alfanumerieke session token die minimaal 22 karakters MOET zijn (zodat hij minimaal 128 bit entropie heeft).

4.3.2 Publiek Internet (HTTPS-OpenID4VP)

In deze variant maakt de app gebruik van het OpenID4VP protocol voor authenticeren richting een organisatie. Dit protocol is gebaseerd op OpenID Connect en OAuth (RFC 6749), met als belangrijkste verschil dat de eindgebruiker (de app) tijdens het protocol rechtstreeks en uitsluitend communiceert met de Relying Party/Verifier (de organisatie), zonder rechtstreekse betrokkenheid van de partij die de identiteit van de eindgebruiker attesteert (de App Manager). Tijdens het protocol authenticeert de app zich richting de organisatie middels een Verifiable Credential, in ons geval de App Manager JWS.

NB: het OpenID4VP protocol is in actieve ontwikkeling, en geregeld worden er nieuwe draft versies van uitgebracht. Deze sectie is gebaseerd op draft 20 van OpenID4VP. Inmiddels bestaan er een aantal nieuwe draft versies.

De eenvoudigste variant van dit protocol ziet er in het algemeen als volgt uit.

OpenID4VP protocol (beknopte weergave)
Figuur 11 OpenID4VP protocol (beknopte weergave)

In het Authorization Request staan de gegevens die de Verifier van de App opvraagt, de nonce die de App moet ondertekenen met de private keys van de Verifiable Credentials die hij gebruikt, en de identiteit van de Verifier. De Authorization Response bevat de disclosure (de Verifiable Presentation(s)).

4.3.2.1 Terminologie

Dezelfde terminologie als in de Terminologie sectie, met daaraan toegevoegd:

  • Authorization Request: een OAuth databericht die de Verifier (OAuth Client) stuurt aan de App (OAuth Authorization Server) met daarin de identiteit van de Verifier, de gevraagde gegevens uit de Verifiable Credential(s), en een nonce (soms ook challenge genoemd) ter verdediging tegen replay attacks.
  • Authorization Response: een OAuth databericht die de App stuurt aan de Verifier, met daarin de Verifiable Presentation.

Tijdens het protocol fungeert de Verifier als een OAuth Client ten opzichte van de App, die fungeert als een OAuth Authorization Server.

Voor de duidelijkheid volgt hier een overzicht van hoe de verschillende standaarden naar de twee partijen refereren.

OAuth OpenID Connect OpenID4VP Deze standaard
Verstuurt Authorization Request Client Client Verifier Verifier
Verstuurt Authorization Response Authorization Server OP (OpenID Provider) Wallet App
4.3.2.2 Cryptografie

Bovenop de "Cryptografie" sectie geldt in deze sectie het volgende:

Elk versleuteld bericht in deze sectie MOET in de vorm van een JWE zijn (RFC 7516; zie ook de Cryptografie sectie hierboven).

4.3.2.3 Verifiable Credentials en Presentations
4.3.2.3.1 Verifiable Credentials

Het Verifiable Credential die de App ontvangt van de App Manager en tijdens authenticatie richting de Verifier presenteert MOET een JWS zijn, met daarin de volgende velden (claims):

Claim naam Claim beschrijving
iss Organisatie-identificatienummer (OIN) van de App Manager
iat Issued At (tijdstip van uitgifte)
nbf Not Before (niet geldig voor)
exp Expiration Time (verloopdatum)
cnf Public key van de App, als in RFC 7800
given_name Voornaam/voornamen
family_name Achternaam/achternamen
bsn Burgerservicenummer

Hierin zijn alle claims behalve de laatste gestandaardiseerd in het IANA "JSON Web Token Claims" register.

De JWS MAG een kid veld in de header bevatten die de public key van de App Manager identificeert waarmee de JWS geverifieerd kan worden.

Voorbeeld:

{
  "typ": "jwt",
  "alg": "ES256",
  "kid": "1"
}
.
{
  "iss": "00000001234567890000", // OIN
  "iat": 1704063600,
  "nbf": 1704063600,
  "exp": 1735686000,
  "cnf": {
    "jwk": {
      "kty": "EC",
      "alg": "ES256",
      "crv": "P-256",
      "use": "sig",
      "x": "2xJs8w74D4glCnAF5W8Ax9EJf6XGSLCTlotBDrMbRd0",
      "y": "YQtuD1-gqVB6XDWIr76jRYL2xNr7YdnV1V7hGogwHgw"
    },
  },
  "given_name": "Willeke Liselotte",
  "family_name": "De Bruijn",
  "bsn": "999991772"
}
4.3.2.3.2 Verifiable Presentation

Tijdens authenticatie van de App richting een Verifier ondertekent de App met diens private key (waarvan de public key in de cnf claim in het Verifiable Credential staat) een willekeurige string, genaamd de nonce, die gegenereerd is door de Verifier. Dit resulteert in een JWS waarin de volgende claims MOETEN staan:

Claim naam Claim beschrijving
aud URL van de Verifier waar de App naar authenticeert
nonce Willekeurige string gegenereerd door de Verifier

Voorbeeld:

{
  "typ": "jwt",
  "alg": "ES256",
}
.
{
  "aud": "https://openid4vp-authentication-process.example.com",
  "nonce": "L9E4aGM9ZzhhC7WLVxa1XKOzie7bzKh0"
}

Vervolgens maakt de App een Verifiable Presentation, die in deze standaard een JSON object is waarin beide JWS MOETEN staan:

{
  "vc": "eyJjc....5TRSJ9", // Verifiable Credential
  "disclosure": "eyJjc....f7B-q2" // Bovenstaande JWS
}

De Verifier MOET de volgende stappen uitvoeren bij het verifiëren van de Verifiable Presentation:

  1. Controleer dat de Verifiable Presentation een JSON object is die de vc en disclosure velden bevat, en dat dit strings zijn.
  2. Verifieer de vc string als JWS tegen de public key(s) van de App Manager(s), eventueel met behulp van het iss veld uit de JWS body en/of het kid veld in de JWS header. Controleer hierbij ook dat het iss veld de OIN bevat van een vertrouwde App Manager, en valideer de nbf en exp velden als in § 4.1 van RFC 7519.
  3. Controleer dat de vc JWS een cnf veld heeft, met daarin een jwk veld, en parse de public key die daarin staat.
  4. Met de public key uit bovenstaande stap, verifieer de disclosure string als JWS.
  5. Controleer dat de disclosure JWS een aud veld heeft en dat de waarde daarvan de URL van de Verifier is.
  6. Controleer dat de disclosure JWS een nonce heeft en dat de waarde daarvan overeenkomt met wat de Verifier eerder had gegenereerd.
  7. Controleer dat de vc JWS alle velden uit de tabel in voorgaande sectie heeft, voor zover niet al gecontroleerd in bovenstaande stappen.
4.3.2.4 Protocolstructuur

In deze sectie beschrijven we het protocol op hoog niveau door keuzes te nemen in bepaalde parameters die de OpenID4VP standaard aanbiedt, en door te beschrijven hoe we encryptie op applicatieniveau realiseren.

4.3.2.4.1 OpenID4VP parameters

De OpenID4VP standaard biedt op een aantal plekken verschillende opties en varianten aan. Deze standaard maakt daarin de volgende keuzes.

  1. "JWT-Secured Authorization Request (JAR)" (RFC 9101). Deze uitbreiding op OAuth en OpenID4VP is optioneel in OpenID4VP maar MOET gebruikt worden in deze standaard. Het voegt het volgende toe:
    • Het Authorization Request wordt door de Verifier digitaal ondertekend in de vorm van een JWS, genaamd de Request Object, zodat de App het Authorization Request kan authenticeren als afkomstig van een bekende Verifier.
    • De Verifier stuurt het Request Object niet rechtstreeks naar de App, maar stuurt in plaats daarvan een URL genaamd de Request URI. De App voert een HTTP GET uit op de Request URI om het Request Object te verkrijgen. Deze uitbreiding is optioneel in RFC 9101, maar MOET in deze standaard gebruikt worden.
  2. "JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)". Deze uitbreiding op OAuth en OpenID4VP is optioneel in OpenID4VP maar MOET gebruikt worden in deze standaard. In deze uitbreiding versleutelt de App de Authorization Response (waarin de Verifiable Presentation staat), in de vorm van een JWE. De App gebruikt voor deze versleuteling een ephemeral (dus verschillend per sessie) public key van de Verifier die de Verifier meestuurt naar de App in het Request Object.
  3. De response_type parameter van het Authorization Request (gedefinieerd in OAuth) MOET de waarde vp_token hebben, gedefinieerd in § 5.4 van OpenID4VP. Deze waarde bepaalt dat de App een Verifiable Presentation op moet nemen in een parameter genaamd vp_token in de Authorization Response.
  4. De waarde van de client_id_scheme parameter van het Authorization Request MOET pre-registered zijn. De waarde van de client_id parameter van het Authorization Request MOET dus per de OpenID4VP standaard een identifier van de Verifier zijn die de App van tevoren al kent. De App gebruikt deze identifier tijdens de sessie om de public keys van de Verifier op te zoeken waarmee het Request Object JWS geverifieerd kan worden en waarnaar de Authorization Response JWE versleuteld kan worden.
  5. De waarde van de scope parameter van het Authorization Request MOET zijn nl.vorijk.oauth_scope.blauwe_knop.vp. Per de OpenID4VP standaard MOETEN de presentation_definition en presentation_definition_uri parameters dus NIET opgenomen zijn in het Authorization Request.
  6. "OAuth 2.0 Multiple Response Type Encoding Practices": voegt een parameter genaamd response_mode toe aan het Authorization Request, die bepaalt hoe de App de Authorization Response terug moet geven. In deze standaard MOET de response_mode parameter de waarde direct_post.jwt hebben, zoals gespecificeerd in § 6.2 van OpenID4VP. Deze waarde bepaalt het volgende:
    • In het Authorization Request MOET de Verifier een response_uri parameter opnemen.
    • De App MOET de Authorization Response naar de response_uri versturen, URL-encoded in een HTTP POST naar de response_uri.
    • De App MOET gebruik maken van JARM, dus de Authorization Response moet versleuteld versturen in de vorm van een JWE.
  7. Bovenstaand response_uri endpoint van de Verifier MOET, als de Verifier de Authorization Response met succes heeft geverifieerd, antwoorden met een JSON object met daarin een redirect_uri parameter. Dit is gedefinieerd als optioneel in § 6.2 van OpenID4VP maar is verplicht in deze standaard. (Deze redirect_uri moet niet verward worden met de identiek genaamde redirect_uri parameter die normaal gesproken in OAuth in het Authorization Request staat.) Er MOET een vers willekeurige string gegenereerd met een CSPRNG in deze request_uri parameter staan zodat deze uniek is per sessie.
4.3.2.4.2 Redirect URI

Het protocol eindigt met de App die van de Verifier de redirect_uri genoemd in het laatste punt hierboven ontvangt. Normaal gesproken in OpenID4VP opent de App vervolgens deze redirect_uri in een browser, zodat daarin de flow van de applicatie verder kan gaan. In deze standaard wordt in plaats daarvan de redirect_uri gebruikt als drager van een access token, in de volgende vorm:

bk-connect://organization-discovery-url/?access-token=example-access-token&access-token-type=OpenID4VP

Het access token hierin verleent de App toegang tot geauthenticeerde endpoints van de Dienst (dat wil zeggen, endpoints die alleen geauthenticeerde gebruikers mogen aanroepen, voor bijvoorbeeld het ophalen van documenten die betrekking hebben op de gebruiker).

4.3.2.4.3 Encryptie

Alle verkeer tussen de App en de (infrastructuur van de) Verifier en/of Dienst MOET gebruik maken van minstens TLS 1.3.

In de praktijk eindigt de TLS-tunnel in de infrastructuur van de Verifier of Dienst vaak bij een reverse proxy, en is het gegevensverkeer dus in plain text zichtbaar voor die reverse proxy en mogelijke middleware die daarachter staat. Daarom gebruikt deze standaard ook encryptie op applicatieniveau (dat wil zeggen, bovenop de TLS-encryptie van de transportlaag) om de gegevens die verstuurd worden tijdens en na de OpenID4VP-sessie te beschermen als volgt.

  • Tijdens het aanmaken van het Request Object MOET de Verifier een ephemeral (dus verschillend per sessie) public/private keypair voor encryptie aanmaken, en de public key hiervan leveren aan de app in het Request Object. De App gebruikt deze als volgt.
    • De App MOET (zoals in de vorige subsectie beschreven) zijn Authorization Response naar deze public key versleutelen middels JARM.
    • Nadat de OpenID4VP-sessie is afgelopen, en de applicatie van de Dienst het overneemt, MAG de App deze public key gebruiken om verdere informatie voor de Dienst te versleutelen op applicatieniveau.
  • Tijdens het aanmaken van het Authorization Response MOET de App een AES key aanmaken, en die meeleveren aan de Verifier in het Authorization Response. (Dit is een toevoeging van deze standaard en niet gedefinieerd in OpenID4VP.) Nadat de OpenID4VP-sessie is afgelopen, en de applicatie van de Dienst het overneemt, MOET de Dienst informatie voor de App versleutelen op applicatieniveau met deze AES key.
4.3.2.5 Protocolbeschrijving

De keuzes beschreven in bovenstaande sectie resulteren bij elkaar in een protocol die we in deze sectie verder uitwerken en expliciet maken.

4.3.2.5.1 Sequence diagram

Het protocol ziet er in een sequence diagram als volgt uit.

OpenID4VP protocol
Figuur 12 OpenID4VP protocol

4.3.2.5.2 Protocolberichten

Er volgt een expliciete beschrijving van de protocolberichten, die refereert aan de genummerde stappen in bovenstaand sequence diagram. Alle whitespace in JSON structuren is enkel bedoeld voor de leesbaarheid van deze standaard en dient niet te worden opgenomen in implementaties.

4.3.2.5.2.1 Stap 1

De App voert een GET uit op de request_uri van de Verifier:

GET /request_uri HTTP/1.1
4.3.2.5.2.2 Stap 4

De Verifier genereert de Request Object JWS, met daarin de volgende velden in de payload:

  • client_id: URL die de Verifier identificeert.
  • response_uri: URL waarnaar de App het Authorization Response dient te sturen.
  • nonce: een willekeurige string gebruik makend van de URL-safe Base64 karakterset, genereerd met een CSPRNG, die minimaal 22 karakters MOET zijn (zodat hij minimaal 128 bit entropie heeft).
  • client_metadata: JSON object met een jwks veld erin, met een keys veld daarin die de ephemeral verifier encryption public key uit Stap 2 bevat, als per RFC 7591 en RFC 7517.

De Verifier MAG een kid veld opnemen in de JWS header om aan te duiden met welke public key de JWS geverifieerd moet worden.

Voorbeeld:

{
  "typ": "jwt",
  "alg": "RS256",
  "kid": "1",
}
.
{
  "response_type": "vp_token",
  "response_mode": "direct_post.jwt",
  "client_id_scheme": "pre-registered",
  "client_id": "https://organization.example.com",
  "response_uri": "https://organization.example.com/response_uri",
  "scope": "nl.vorijk.oauth_scope.blauwe_knop.vp",
  "nonce": "L9E4aGM9ZzhhC7WLVxa1XKOzie7bzKh0",
  "client_metadata": {
    "jwks": {
      "keys": [{
        "kty": "EC",
        "crv": "P-256",
        "alg": "ECDH-ES",
        "use": "enc",
        "x": "GD006BBz6L9x1cQZQtihWeL_CBcJqjMerlFhGNHt6q8",
        "y": "dUCZyFZXdDNDTC_mRRveNtY_qT8D-LCDGoaNwE8i8rU"
      }]
    }
  }
}

De Verifier antwoordt het GET request uit stap 1 met bovenstaande JWS als volgt:

HTTP/1.1 200 OK
Content-type: application/oauth-authz-req+jwt

eyJhb...x5Nz-g
4.3.2.5.2.3 Stap 7 t/m 9

Gegeven het Verifiable Credential produceert de App een Verifiable Presentation per de "Verifiable Presentation" sectie hierboven. Vervolgens plaatst de App de Verifiable Presentation in het vp_token veld in de Authentication Response, samen met de ephemeral app encryption public key.

Voorbeeld:

{
  "vp_token": {
    "vc": "eyJjc....5TRSJ9",
    "disclosure": "eyJjc....f7B-q2"
  },
  "presentation_submission": {
    "id": "nl.vorijk.presentation_submission.blauwe_knop",
    "definition_id": "nl.vorijk.presentation_definition.blauwe_knop",
    "descriptor_map": [
      {
        "id": "nl.vorijk.descriptor_map.blauwe_knop",
        "format": "jwt",
        "path": "$",
        "path_nested": {
          "format": "jwt",
          "path": "$.vc"
        }
      }
    ]
  },
  "jwks": {
    "keys": [{
      "kty": "oct",
      "alg": "A128KW",
      "k": "GawgguFyGrWKav7AX4VKUg"
    }]
  }
}

Hierin MOET presentation_submission altijd bovenstaande waarde hebben, per § 6.1 van OpenID4VP. Dit geeft aan de Verifier aan waar deze het Verifiable Credential kan vinden binnen de ontvangen Verifiable Presentation.

Het jwks veld hierin maakt het mogelijk voor de app om een AES encryption key te versturen waarmee de app en de gebruikende applicatie data op applicatieniveau kunnen versleutelen, wanneer ze verkeer naar elkaar sturen nadat de OpenID4VP-sessie is afgerond. Dit is een toevoeging van deze standaard en niet gedefinieerd in OpenID4VP. De JSON-structuur van het jwks veld is gedefinieerd in RFC 7591 en RFC 7517 en net als in het Request Object. Bovenstaand voorbeeld maakt gebruik van de A128KW waarde voor alg, als gedefinieerd in § 4.1 van RFC 7518, welke aangeeft dat wanneer deze key gebruikt wordt om een JWE mee te maken deze JWE ook gebruik moet maken van A128KW voor alg. Andere waardes uit deze RFC die gebruikt MOGEN worden:

  • A192KW
  • A256KW
  • dir

Na het produceren van bovenstaand Authorization Response versleutelt de App hem naar de ephemeral verifier encryption public key uit het Request Object, door het op te nemen als payload in een JWE als in § 6.3 van OpenID4VP, en stuurt het op naar de response_uri uit het Request Object, als volgt:

POST /response_uri HTTP/1.1
Content-Type: application/x-www-form-urlencoded

response=eyJra...9t2LQ
4.3.2.5.2.4 Stap 12

De Verifier MOET de Verifiable Presentation in de Authorization Response valideren als in § 6.5 van OpenID4VP en de "Verifiable Presentation" sectie hierboven.

4.3.2.5.2.5 Stap 14

De Verifier genereert met een CSPRNG een willekeurige alfanumerieke access-token die minimaal 32 karakters MOET zijn, en plaatst deze in een URI van de volgende vorm:

bk-connect://organization-discovery-url/?access-token=9YryEzKheqpx5iS2JsDNRHoydCBIsAKV&access-token-type=OpenID4VP
4.3.2.5.2.6 Stap 17

De Verifier antwoordt op de HTTP POST uit stap 10 met bovenstaande URI als volgt:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "redirect_uri": "bk-connect://organization-discovery-url/?access-token=9YryEzKheqpx5iS2JsDNRHoydCBIsAKV&access-token-type=OpenID4VP"
}

Als het valideren van de Authorization Response faalt MOET de Verifier in plaats van bovenstaande antwoorden als in § 6.4 van OpenID4VP.

4.4 Hulpmiddelen activeren

4.4.1 Publiek internet (HTTPS-JWT)

Dit protocol maakt gebruik van het CreateSession protocol voor het uitgeven of verversen van een Verifiable Credential, met certificate_type_self_signed als waarde voor de certificate_type parameter. Hiermee wordt het volgende bereikt:

  • De App maakt de public key die in het Verifiable Credential moet komen kenbaar aan de Credential Issuer, en bewijst tegelijk controle te hebben over de corresponderende private key.
  • Er wordt een AES key bepaald waarmee de rest van het verkeer in dit protocol versleuteld wordt, bovenop de encryptie van de transportlaag (TLS).

Vervolgens opent de App de browser om daarin de gebruiker te identificeren en authenticeren, middels DigiD. Indien dit slaagt wordt de app weer vanuit de browser geopend middels de Universal Link van de App, met een registration_token als (versleutelde) parameter, die daarna ingewisseld kan worden bij de Credential Issuer voor het Verifiable Credential.

Nadat het Verifiable Credential is geregistreerd geldt de gebruiker als geregistreerd bij de Credential Issuer. De App en de Credential Issuer slaan het registration_token beiden op voor later hergebruik. De Credential Issuer slaat daarbij ook de attributen van de gebruiker op die hij eerder in het Verifiable Credential heeft uitgegeven. Wanneer het Verifiable Credential van de App is verlopen, kan deze middels het eerder ontvangen registration_token een vers Verifiable Credential opvragen bij de Credential Isser.

4.4.1.1 Protocolbeschrijving
4.4.1.1.1 Sequence diagram

Het protocol ziet er in een sequence diagram als volgt uit.

`Issuance` protocol
Figuur 13 Issuance protocol

4.4.1.1.2 Protocolberichten

Er volgt een expliciete beschrijving van de protocolberichten, die refereert aan de genummerde stappen in bovenstaand sequence diagram. Alle whitespace in JSON structuren is enkel bedoeld voor de leesbaarheid van deze standaard en dient niet te worden opgenomen in implementaties.

4.4.1.1.2.1 Stap 2

De App en de Credential Issuer voeren het CreateSession protocol uit. De App MOET hierbij voor de certificate_type parameter de waarde certificate_type_self_signed gebruiken. Dit protocol resulteert in een session_token en een AES key voor later gebruik.

4.4.1.1.2.2 Stap 3

De App navigeert naar https://credential-issuer.example.com/register_app?session_token=..., waarbij het session_token uit de vorige stap wordt ingevuld.

(NB: in andere protocollen in deze standaard wordt het session_token uit het CreateSession protocol verstuurd in de Authorization HTTP header van een POST request. Dat is in dit geval echter niet mogelijk. Daarom wordt het session_token in dit geval middels een URL parameter in de URL van de issuer meegegeven.)

4.4.1.1.2.3 Stap 6 en 7

De eindgebruiker wordt geïndentificeerd middels DigiD want resulteert in diens BSN.

4.4.1.1.2.4 Stap 10

De Credential Issuer genereert met een CSPRNG een willekeurige alfanumerieke registration_token die minimaal 22 karakters MOET zijn (zodat hij minimaal 128 bit entropie heeft).

4.4.1.1.2.5 Stap 13

De Credential Issuer maakt een JSON object met daarin de volgende velden:

  • sub: MOET de vaste waarde registration_token hebben.
  • iss: de URL van de Credential Issuer (dat wil zeggen, de URL waar de App naartoe navigeert in stap 3, zonder register_app?session_token=...).
  • registration_token: het registration_token uit stap 8.

Voorbeeld:

{
  "sub": "registration_token",
  "iss": "https://credential-issuer.example.com/",
  "registration_token": "LarRGSbmUPYtRYO6BQ4yn8"
}

Vervolgens versleutelt de Credential Issuer dit object met de session AES key in de vorm van een JWE (zie de Cryptografie sectie hierboven).

4.4.1.1.2.6 Stap 14

De Credential Issuer roept de Universal Link van de App aan, bijvoorbeeld door de Universal Link te plaatsen in een link op zijn website die de eindgebruiker moet gebruiken, of door een HTTP redirect naar de Universal Link. De Credential Issuer levert de volgende parameters URL-encoded mee in de Universal Link:

  • registration_token: het registration token JWE uit de vorige stap.

De app ontvangt de Universal Link en parseert daaruit de registration_token.

Voorbeeld:

https://app.vorijk.nl/ul/issuance?registration_token=eyBwMry...

NB: de reden voor deze tussenstap waarin een registration_token wordt gegeven aan de app, in plaats van rechtstreeks het Verifiable Credential, is om ervoor te zorgen dat het Verifiable Credential in een latere stap rechtstreeks door de App bij de Credential Issuer kan worden opgehaald, in plaats van dat het Verifiable Credential in deze stap ook nog eens door de browser heen zou gaan voordat hij bij de App terecht komt. Bovendien zou het encoderen van het Verifiable Credential in de Universal Link deze dermate groot kunnen maken dat hij door het mobiele besturingssysteem wordt afgekapt.

4.4.1.1.2.7 Stap 15 en 16

De App ontsleutelt de JWE met de session AES key, en valideert dat:

  1. dit resulteert in een JSON object, en
  2. dat dit JSON object de velden uit Stap 11 bevat, met iss en sub de waardes zoals daar gespecificeerd.
4.4.1.1.2.8 Stap 19

De App maakt een JSON object met daarin de volgende velden:

  • sub: MOET de vaste waarde registration_token hebben.
  • iss: MOET de vaste waarde bk-connect://app/ hebben.
  • registration_token: het registration_token uit stap 8.

Voorbeeld:

{
  "sub": "registration_token",
  "iss": "bk-connect://app/",
  "registration_token": "LarRGSbmUPYtRYO6BQ4yn8"
}

Vervolgens versleutelt de App dit object met de session AES key in de vorm van een JWE (zie de Cryptografie sectie hierboven).

4.4.1.1.2.9 Stap 20

De App verstuurt het versleutelde registration_token object naar de Credential Issuer, middels een HTTP POST naar /credential, met het session_token uit Stap 2 in de Authorization HTTP header.

Voorbeeld:

POST /credential HTTP/1.1
Host: credential-issuer.example.com
Authorization: tFNqe50B2nRSwo59ghKd6O

eyNaIioBb2_Jhb...x5Nz-g

NB: de reden dat de gebruiker het registration_token eerst moet ontsleutelen in Stap 13 en dan opnieuw moet versleutelen in Stap 15, in plaats van dat de gebruiker de versleutelde JWE die hij ontvangt in stap 12 rechtstreeks in deze stap zou kunnen versturen, is om het onmogelijk te maken voor een aanvaller die binnenin de TLS tunnel zit, en die dus het verkeer tussen de App en Credential Issuer kan zien, om de versleutelde JWE in stap 12 op te vangen en die dan in deze stap te versturen in plaats van de echte gebruiker, om op die manier het Verifiable Credential te stelen.

4.4.1.1.2.10 Stap 23 t/m 24

De Credential Issuer ontsleutelt de JWE uit de HTTP POST body van de App met de session AES key, en valideert dat:

  1. dit resulteert in een JSON object, en
  2. dat dit JSON object de velden uit Stap 14 bevat, met iss en sub de waardes zoals daar gespecificeerd.
4.4.1.1.2.11 Stap 28

De Credential Issuer tekent met zijn private key het Verifiable Credential, in de vorm van een JWS. Hierbij plaatst hij de root app EC public key in het app_public_key veld van de Verifiable Credential JWS. Zie de Verifiable Credentials sectie hierboven voor alle velden en een voorbeeld.

4.4.1.2 Deregistratie

De App kan zichzelf deregisteren bij de Credential Issuer om aan te geven dat hij geen vers Verifiable Credential meer zal opvragen middels het protocol gedocumenteerd in deze sectie.

Nadat de Credential Issuer dit protocol heeft uitgevoerd voor een zeker registration_token, dan MOET de Credential Issuer eventuele latere aanroepingen van het /credential HTTP endpoint in het uitgifteprotocol van bovenstaande sectie die gebruik maken van het betreffende registration_token afbreken met een foutmelding.

4.4.1.2.1 Sequence diagram

Het protocol ziet er in een sequence diagram als volgt uit.

`Deregistratie` protocol
Figuur 14 Deregistratie protocol

4.4.1.2.2 Protocolberichten

Er volgt een expliciete beschrijving van de protocolberichten, die refereert aan de genummerde stappen in bovenstaand sequence diagram. Alle whitespace in JSON structuren is enkel bedoeld voor de leesbaarheid van deze standaard en dient niet te worden opgenomen in implementaties.

4.4.1.2.2.1 Stap 2

De App en de Credential Issuer voeren het CreateSession protocol uit. De App MOET hierbij voor de certificate_type parameter de waarde app_manager_jwt_certificate gebruiken. Dit protocol resulteert in een session_token en een AES key voor later gebruik.

4.4.1.2.2.2 Stap 3

De App maakt een JSON object met daarin de volgende velden:

  • sub: MOET de vaste waarde unregister_app hebben.
  • iss: MOET de vaste waarde bk-connect://app/ hebben.
  • registration_token: het registration_token van de App.

Voorbeeld:

{
  "sub": "unregister_app",
  "iss": "bk-connect://app/",
  "registration_token": "LarRGSbmUPYtRYO6BQ4yn8"
}

Vervolgens versleutelt de App bovenstaand object met de session AES key in de vorm van een JWE (zie de Cryptografie sectie hierboven).

4.4.1.2.2.3 Stap 4

De App verstuurt het JWE naar de Credential Issuer, middels een HTTP POST naar /unregister_app, waarbij het session_token uit Stap 2 wordt meegegeven in de Authorization HTTP header.

Voorbeeld:

POST /unregister_app HTTP/1.1
Host: credential-issuer.example.com
Authorization: tFNqe50B2nRSwo59ghKd6O

eyNaIioBb2_Jhb...x5Nz-g
4.4.1.2.2.4 Stap 7 en 8

De Credential Issuer ontsleutelt de JWE uit de HTTP POST body van de App met de session AES key, en valideert dat:

  1. dit resulteert in een JSON object, en
  2. dat dit JSON object de velden uit Stap 3 bevat, met iss en sub de waardes zoals daar gespecificeerd.
4.4.1.2.2.5 Stap 9

De Credential Issuer verwijdert de registratie onder registration_token, of markeert deze als zijnde inactief, zodat een eventuele latere aanroep van het /credential HTTP endpoint in het uitgifteprotocol van voorgaande sectie die gebruik maakt van het betreffende registration_token afbreekt met een foutmelding.

4.4.2 Publiek Internet (HTTPS-OpenID4VCI)

In deze variant maakt de app gebruik van het OpenID4VCI protocol voor het verkrijgen van een Verifiable Credential waarmee de app zich later kan authenticeren richting dienstverleners. Dit protocol kent twee varianten: de Authorized Code Flow en de Pre-Authorized Code Flow. Deze standaard maakt gebruik van de Authorized Code Flow. Deze flow kan gezien worden als een uitbreiding van OAuth (RFC 6749), en doet twee dingen:

  • Het identificeert middels (een uitbreiding van) OAuth de eindgebruiker van de app richting de uitgever van het Verifiable Credential (de App Manager),
  • Het geeft een (of meer) Verifiable Credential(s) uit aan de app.

NB: het OpenID4VCI protocol is in actieve ontwikkeling, en geregeld worden er nieuwe draft versies van uitgebracht. Deze sectie is gebaseerd op draft 13 van OpenID4VCI. Inmiddels bestaan er een aantal nieuwe draft versies.

4.4.2.1 Terminologie

Dezelfde terminologie als in de terminologie sectie, met daaraan toegevoegd:

  • Proof of possession: een databericht die (1) een public key en vaak ook een nonce bevat, en (2) een digitale handtekening over die public key en nonce, gezet met de bijbehorende private key. Dit communiceert aan de ontvangende partij niet alleen de public key, maar toont ook aan dat degene die hem stuurt controle heeft over de bijbehorende private key.
4.4.2.2 Introductie

In deze standaard ziet dit protocol er schematisch als volgt uit. Dit diagram toont in de tweede regel binnen de haakjes telkens de belangrijkste gegevens die verstuurd worden.

OpenID4VCI protocol (beknopte weergave)
Figuur 15 OpenID4VCI protocol (beknopte weergave)

Dit kan gezien worden als een OAuth sessie die toegang verschaft tot het Credential endpoint onderaan, waarbij de app de rol speelt van zowel de User Agent als de OAuth Client.

In implementaties kunnen de Credential Issuer en de Authorization Server één en dezelfde server zijn die beide rollen vervult. In bovenstaand diagram worden ze apart getoond om verantwoordelijkheden te scheiden en om de gelijkenis met OAuth aan te tonen.

Refererend naar de genummerde stappen gebeurt het volgende in het protocol:

  • stap 1, 2: de app verkrijgt de issuer metadata middels een GET op een JSON datastructuur die de issuer publiceert onder /.well-known/openid-credential-issuer. De issuer publiceert daarin gegevens over zichzelf, onder andere de URL naar de Authorization Server die hij gebruikt. De app gebruikt vervolgens het OAuth metadata discovery mechanisme (RFC 8414) om de OAuth metadata van de Authorization Server te verkrijgen.
  • stap 3, 4: de app opent een browser en verstuurt daarbij een Authorization Request in het GET request van de browser. In de browser wordt de eindgebruiker geïdentificeerd en geauthenticeerd bijvoorbeeld middels gebruikersnaam/wachtwoord of een identificatieapp zoals DigiD. Als identificatie slaagt wordt de Authorization Response naar de app gestuurd, met daarin een authorization code. De app opent en parse't de authorization code uit de Authorization Response.
  • stap 5, 6: de app wisselt de authorization code in voor een access token en een c_nonce. Het access token geeft toegang tot het Credential endpoint van de issuer, welke een OAuth 2.0 protected resource is als in RFC 6750.
  • stap 7: de app tekent het c_nonce, resulterend in een proof of possession.
  • stap 8: de app stuurt het proof of possession op naar de issuer, samen met het access token.
  • stap 9, 10: de issuer gebruikt het access token om bij de Authorization Server op te halen om welke gebruiker het gaat, en welke c_nonce aan de gebruiker gegeven is.
  • stap 11: de issuer controleert dat het proof of possession een geldige signature is over de c_nonce. Zoja maakt hij een Verifiable Credential met daarin de public key uit het proof of possession en de attributen van de gebruiker, en stuurt deze naar de app.
4.4.2.3 Asymmetrische encryptie

Elk versleuteld bericht in deze sectie MOET in de vorm van een JWE zijn (RFC 7516, zie ook de Cryptografie sectie hierboven).

4.4.2.4 Protocolstructuur

In deze sectie beschrijven we het protocol op hoog niveau door keuzes te nemen in bepaalde parameters die de OpenID4VCI standaard aanbiedt.

4.4.2.4.1 Credential Issuer metadata

De Credential Issuer MOET onder GET /.well-known/openid-credential-issuer een JSON datastructuur zoals de volgende publiceren (zonder commentaar):

{
  "credential_issuer": "https://credential-issuer.example.com",
  "credential_endpoint": "https://credential-issuer.example.com/credential",
  "credential_identifiers_supported": false,
  "credential_response_encryption": {
    "encryption_required": true, // (1)
    "alg_values_supported" : [ "ECDH-ES" ], // (2)
    "enc_values_supported" : [ "A128GCM", "A192GCM", "A256GCM" ] // (3)
  },
  "credential_configurations_supported": {
    "nl.vorijk.vc.blauwe_knop": { // (4)
      "scope": "nl.vorijk.oauth_scope.blauwe_knop.vc",
      "format": "jwt",
      "cryptographic_binding_methods_supported": [ "jwk" ],
      "credential_signing_alg_values_supported": [ "ES256" ], // (5)
      "proof_types_supported": {
        "jwt": {
          "proof_signing_alg_values_supported": [ "ES256" ] // (6)
        }
      }
    }
  }
}

Er volgt een korte uitleg van sommige van de parameters (voor meer informatie, zie § 11.2.3 van OpenID4VCI). Refererend naar de nummers hierboven:

  1. encryption_required kondigt aan dat de Credential Issuer het Verifiable Credential aan het eind van het protocol in versleutelde vorm zal geven aan de app, en dat de app daar voorafgaand bij het Credential Request daarom een public key zal moeten aanleveren waarnaar het Verifiable Credential versleuteld gaat worden.
  2. Toegestane waardes voor de alg JWE header parameter. Per de "Asymmetrische encryptie" sectie hierboven MOET deze array enkel ECDH-ES bevatten.
  3. Toegestane waardoes voor de enc JWE header parameter. Per de "Asymmetrische encryptie" sectie hierboven MOET dit A128GCM, A192GCM, A256GCM zijn; het MAG ook een subset van die drie zijn als de Credential Issuer niet alledrie ondersteunt.
  4. Dit object publiceert metadata over het Verifiable Credential wat de Credential Issuer aanbiedt.
  5. Deze array bevat de algoritmes die de Credential Issuer kan gebruiken voor het ondertekenen van het Verifiable Credential. In deze standaard MOET deze array enkel het algoritme bevatten waarmee het Verifiable Credential ondertekend wordt.
  6. Array van algoritmes ondersteund door de Credential Issuer die de app mag gebruiken voor het maken van het Proof of Possession.
4.4.2.4.2 OAuth metadata

De Credential Issuer metadata MAG volgens § 11.2.3 van OpenID4VCI een array genaamd authorization_servers bevatten, welke URLs bevat van OAuth server(s) die de app mag gebruiken voor het versturen van de Authorization Request en Token Request. De afwezigheid daarvan betekent dat de Credential Issuer zelf fungeert als OAuth server, dat wil zeggen de Authorization en Token endpoints host. Deze moet dan ook een OAuth 2.0 metadata document publiceren onder .well-known/oauth-authorization-server. Deze MOET minimaal als volgt zijn, maar MAG ook andere velden als gedefinieerd in RFC 8414 bevatten:

{
  "issuer": "https://oauth-server.example.com",
  "authorization_endpoint": "https://oauth-server.example.com/authorize",
  "token_endpoint": "https://oauth-server.example.com/token",
  "response_types_supported":  ["code"],
  "grant_types_supported": ["authorization_code"],
  "code_challenge_methods_supported": ["S256"]
}
4.4.2.4.3 OpenID4VCI parameters

De OpenID4VCI standaard biedt op een aantal plekken verschillende opties en varianten aan. Deze standaard maakt daarin de volgende keuzes.

  1. "Proof Key for Code Exchange (PKCE)" (RFC 7636, wordt uitgesproken als "pixy"). Deze uitbreiding op OAuth authenticeert de app bij het Token Request als zijnde dezelfde app die het Authorization Request stuurde, doordat de app bij het Authorization Request de (SHA256) hash van een willekeurig secret moet sturen, en bij het Token request het secret zelf. Dit voorkomt dat een aanvaller die erin slaagt om het authorization code te onderscheppen deze kan gebruiken om het access token te bemachtigen.
  2. "Demonstrating Proof of Possession (DPoP)" (RFC 9449): deze uitbreiding op OAuth vervult een vergelijkbare rol als PKCE, maar dan bij het Credential Request. Het authenticeert de app bij het Credential Request als zijnde dezelfde app die het Token Request verstuurde, doordat de app bij het versturen van het Token Request een ephemeral public key aankondigt waarmee hij vervolgens het access token ondertekent bij het Credential Request. Dit voorkomt dat een aanvaller die erin slaagt om het access token te onderscheppen deze kan gebruiken om het Verifiable Credential te bemachtigen.
  3. In het Authorization Request MOET de app middels de authorization_details parameter, als in § 5.1.1 van OpenID4VCI, aangeven welk Verifiable Credential hij geïssued wil krijgen:
    [{
        "type": "openid_credential",
        "credential_configuration_id": "nl.vorijk.vc.blauwe_knop"
    }]
    
    Het credential_configuration_id refereert naar de corresponderende entry in de credential_configurations_supported object in de Credential Issuer metadata. Dit object MOET ook worden opgenomen in het Token Response.
  4. In het Token Response MOET een c_nonce parameter worden opgenomen, die een willekeurige string bevat. Deze moet door de app ondertekend worden met de private key waarvan de public key in het Verifiable Credential moet komen, resulterend in een Proof of Possession.
  5. Het Credential Request MOET de Proof of Possession bevatten in de proof parameter, en een credential_response_encryption object waarin de app een ephemeral ECDH-ES public key zet waarnaar de Credential Issuer het Verifiable Credential moet versleutelen.
  6. Het Credential Response MOET door de Credential Issuer in de vorm van een JWE versleuteld worden naar de public key in het credential_response_encryption object in het Credential Request.

OpenID4VCI maakt het gebruik van PAR (Pushed Authorization Requests, RFC 9126) optioneel voor het versturen van het Authorization Request. In deze uitbreiding stuurt de OAuth Client het Authorization Request niet via de User Agent van de eindgebruiker naar de Authorization Server, maar stuurt de Client het Authorization Request rechtstreeks in een HTTP POST naar de Authorization Server. Deze antwoordt vervolgens met een referentie naar de sessie genaamd de request_uri, die de eindgebruiker in de URL naar het Authorization Endpoint stopt wanneer hij daar naartoe navigeert. De Authorization Server herkent de request_uri en weet daardoor om welk Authorization Request het gaat. Dit biedt in traditionele OAuth-gebaseerde protocollen drie voordelen:

  1. Integriteit van het Authorization Request: doordat het Authorization Request niet meer via de User Agent van de eindgebruiker wordt verstuurd, kan deze ook niet worden aangepast door de eindgebruiker, diens browser, of een man-in-the-middle tussen de eindgebruiker en de Client of Authorization Server.
  2. Vertrouwelijkheid van het Authorization Request: doordat het Authorization Request rechtstreeks van de Client naar de Authorization Server gaat kan deze desgewenst ook geheime informatie bevatten, zoals bijvoorbeeld een identificatietoken van de Client richting de Authorization Server of persoonsgegevens van de eindgebruiker.
  3. Het voorkomt problemen als het Authorization Request groter is dan ondersteund wordt in URLs.

Deze uitbreiding MAG NIET gebruikt worden in deze standaard. De reden hiervoor is dat het wel complexiteit en runtime kosten met zich meebrengt, terwijl beide bovenstaande voordelen die het biedt in traditionele OAuth in dit protocol niet van toepassing zijn:

  • In het OpenID4VCI protocol zijn de eindgebruiker en de client dezelfde partij, waardoor de eerste twee punten wegvallen.
  • In deze standaard is het Authorization Request nooit dermate groot dat deze niet in een URL zou passen.
4.4.2.5 Protocolbeschrijving

De keuzes beschreven in bovenstaande sectie resulteren bij elkaar in een protocol die we in deze sectie verder uitwerken en expliciet maken.

4.4.2.5.1 Sequence diagram

Het protocol ziet er in een sequence diagram als volgt uit. In dit diagram wordt de rol van de Authorization Server en de Credential Issuer gespeeld door dezelfde partij, maar we voegen DigiD en BRP (Basisregistratie Personen) als partijen toe. Verder nemen we aan dat de Authorization, Token en Credential endpoints /authorize, /token en /credential zijn respectievelijk. Net als in het vorige diagram tonen we telkens in de tweede regel binnen haakjes de belangrijkste gegevens die verstuurd worden. (Deze lijst is meestal niet compleet, dat wil zeggen dat er vaak meer wordt verstuurd dan wat in deze tweede regel staat; we tonen hier alleen de belangrijkste gegegvens.)

OpenID4VCI protocol
Figuur 16 OpenID4VCI protocol

4.4.2.5.2 Protocolberichten

Er volgt een expliciete beschrijving van de protocolberichten, die refereert aan de genummerde stappen in bovenstaand sequence diagram. Alle whitespace in JSON structuren en HTTP requests is enkel bedoeld voor de leesbaarheid van deze standaard en dient niet te worden opgenomen in implementaties.

In onderstaand protocol wordt een aantal keer Base64-encodering gebruikt. Dit moet altijd de URL-safe variant zijn zonder padding.

4.4.2.5.2.1 Stap 1 en 2

De App gebruikt de OpenID4VCI en OAuth metadata discovery mechanismes door een GET uit te voeren op /.well-known/openid-credential-issuer en /.well-known/oauth-authorization-server, respectievelijk. De server(s) antwoorden met JSON structuren zoals in de Credential Issuer metadata en OAuth metadata secties hierboven. De App parseert de JSON en ontdekt op die manier de URLs van de Authorization, Token en Credential endpoints.

In het vervolg van dit document nemen we aan dat deze endpoints als volgt zijn:

  • https://issuer.example.com/authorize
  • https://issuer.example.com/token
  • https://issuer.example.com/credential
4.4.2.5.2.2 Stap 3

De App genereert een PKCE verifier (genaamd code_verifier in onderstaande HTTP berichten) door 32 willekeurige bytes te genereren met een CSPRNG en deze te Base64url-encoderen, resulterend in een PKCE verifier van 43 karakters. De App genereert vervolgens de bijbehorende PKCE challenge middels de volgende pseudocode:

code_challenge := BASE64URL-ENCODE(SHA256(code_verifier))

Zie ook § 4.1 en 4.2 van RFC 7636.

4.4.2.5.2.3 Stap 4

De App navigeert in de browser naar het Authorization endpoint van de Credential Issuer, met URL-encoded in de URL het Authorization Request als in § 5 van OpenID4VCI en § 4.1.1 van OAuth, met de volgende parameters:

  • response_type: MOET de waarde code hebben (refererend naar de authorization code grant type van § 4.1 van OAuth).
  • client_id: een identifier van de App die een vaste waarde MOET hebben over alle App instanties, bijvoorbeeld nl.vorijk.app.
  • code_challenge: de PKCE challenge gegenereerd zoals hierboven.
  • code_challenge_method: MOET de waarde S256 hebben (per § 4.2 van de PKCE RFC).
  • scope: MOET de waarde nl.vorijk.oauth_scope.blauwe_knop.vc hebben, welke refereert naar de corresponderende scope uit de Credential Issuer Metadata.
  • redirect_uri: dit MOET een Universal Link (UL) zijn die de App opent. Nadat authenticatie en identificatie van de eindgebruiker is gelukt zal de gebruiker in Stap 10 naar deze link worden geredirect door de Credential Issuer, waardoor de App opent.
  • state: MAG aanwezig zijn en de waarde hiervan mag vrij bepaald worden door de App. Als state gebruikt wordt dan ontvangt de App dezelfde state ook terug in het Authorization Response, zie stap 10. De App kan deze parameter gebruiken voor het bijhouden van bepaalde state, bijvoorbeeld voor het tracken van verschillende sessies.

Voorbeeld (met newlines voor leesbaarheid):

https://issuer.example.com/authorize?
  response_type=code
  &client_id=nl.vorijk.app
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
  &scope=nl.vorijk.oauth_scope.blauwe_knop.vc
  &redirect_uri=https%3A%2F%2Fapp.vorijk.nl%2Ful%2Fissuance
  &state=xyz
4.4.2.5.2.4 Stap 5 en 6

De eindgebruiker wordt geïndentificeerd middels DigiD want resulteert in diens BSN.

4.4.2.5.2.5 Stap 7

De Credential Issuer genereert met een CSPRNG een nieuwe authorization code, die een willekeurige string gebruik makend van de URL-safe Base64 karakterset MOET zijn, van minimaal 22 karakters (zodat hij minimaal 128 bit entropie heeft).

4.4.2.5.2.6 Stap 8 en 9

De Credential Issuer slaat de PKCE challenge en het BSN van de gebruiker op onder het authorization code voor later gebruik.

4.4.2.5.2.7 Stap 10

De Credential Issuer roept de redirect_uri uit Stap 4 met daarin de Universal Link van de App aan, bijvoorbeeld door de Universal Link te plaatsen in een link op zijn website die de eindgebruiker moet gebruiken, of door een HTTP redirect naar de Universal Link. De Credential Issuer levert de volgende parameters URL-encoded mee in de Universal Link:

  • code: de authorization code.
  • state: alleen aanwezig als de App in het Authorization Request (stap 4) een state parameter heeft meegegeven, in dat geval met dezelfde waarde als in het Authorization Request.

De app ontvangt de Universal Link en parseert daaruit de authorization code.

Voorbeeld:

https://app.vorijk.nl/ul/issuance?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
4.4.2.5.2.8 Stap 11

De App genereert een nieuw ephemeral EC keypair, en produceert daarmee een DPoP Proof of Possession per § 4.2 van RFC 9449, welke een JWS is als volgt:

{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "x": "l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y": "9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv": "P-256"
  }
}
.
{
  "jti": "-BwC3ESc6acc2lTc",
  "htm": "POST",
  "htu": "https://issuer.example.com/token",
  "iat": 1562262616
}

In deze JWS zijn de velden als volgt:

  • jwk: de zojuist gegenereerde public key in JWK formaat (RFC 7517);
  • jti: De Base64url-encoding van minimaal 12 bytes aan willekeurige data gegenereerd met een CSPRNG;
  • htm: de HTTP methode waarbij deze DPoP in de volgende stap gebruikt wordt;
  • htu: de URL waarbij deze DPoP in de volgende stap gebruikt wordt;
  • iat: de Unix timestamp van het moment van creatie van deze JWS.
4.4.2.5.2.9 Stap 12

De App doet een Token Request als in § 6 van OpenID4VCI en § 4.1.3 van OAuth bij de Credential Issuer, gebruik makend van de authorization code die hij eerder heeft ontvangen. De App stuurt hierbij ook bovenstaand DPoP Proof of Possession mee, per § 4.1 van RFC 9449.

De App verstuurt het Token Request URL-encoded in de HTTP POST body, met de volgende parameters:

  • grant_type: MOET de waarde authorization_code hebben.
  • client_id en redirect_uri: MOETEN dezelfde waardes als in het Authorization Request hebben.
  • code: de authorization code ontvangen in stap 10.
  • code_verifier: de PKCE verifier gegenereerd in stap 3.

Voorbeeld (met newlines voor leesbaarheid):

POST /token HTTP/1.1
Host: issuer.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik
 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR
 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE
 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj
 oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia
 WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg
 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg

grant_type=authorization_code
&client_id=nl.vorijk.app
&redirect_uri=https%3A%2F%2Fapp.vorijk.nl%2Ful%2Fissuance
&code=SplxlOBeZQQYbYS6WxSbIA
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
4.4.2.5.2.10 Stap 13 en 14

De Credential Issuer haalt middels de authorization code de PKCE challenge en het BSN van de gebruiker op.

4.4.2.5.2.11 Stap 15

De Credential Issuer verifieert de PKCE verifier per § 4.6 van RFC 7636, door vast te stellen dat het volgende geldt:

code_challenge == BASE64URL-ENCODE(SHA256(code_verifier))

Als deze gelijkheid niet geldt, dan MOET de Credential Issuer afbreken met de foutmelding invalid_grant als per § 5.2 van OAuth.

4.4.2.5.2.12 Stap 16

De Credential Issuer verifieert de DPoP Proof of Possession uit de DPoP HTTP header middels de instructies in § 4.3 van RFC 9449.

Als de DPoP JWS niet geldig is, dan MOET de Credential Issuer afbreken met de foutmelding invalid_dpop_proof als per § 5.2 van OAuth.

Als de DPoP JWS wel geldig is, dan parseert de Credential Issuer de DPoP public key in de DPoP JWS voor later gebruik.

4.4.2.5.2.13 Stap 17

De Credential Issuer genereert met een CSPRNG een nieuw access_token en c_nonce, die beiden willekeurige strings gebruik makend van de URL-safe Base64 karakterset MOETEN zijn, van minimaal 22 karakters (zodat ze minimaal 128 bit entropie hebben).

4.4.2.5.2.14 Stap 18 en 19

De Credential Issuer slaat het BSN van de gebruiker, de c_nonce en de DPoP public key op onder het access_token voor later gebruik.

4.4.2.5.2.15 Stap 20

De Credential Issuer antwoordt op het HTTP POST request van de App uit stap 12 met een JSON object met daarin de volgende parameters:

  • access_token: het access token gegenereerd in de vorige stap, die toegang geeft tot het Credential Endpoint (zie Stap 25).
  • c_nonce: de nonce gegenereerd in de vorige stap.
  • token_type: MOET de waarde DPoP hebben per § 5 van RFC 9449, wat aangeeft aan de App dat DPoP gebruikt MOET worden bij het gebruik van het access token (dus bij het opvragen van het Verifiable Credential).
  • expires_in: MAG aanwezig zijn en MOET in dat geval in seconden aangeven hoe lang het access token geldig is.

Voorbeeld:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "access_token": "JhbGciOiJSUzI1NiIsInR5",
  "c_nonce": "LarRGSbmUPYtRYO6BQ4yn8",
  "token_type": "DPoP",
  "expires_in": 60,
}
4.4.2.5.2.16 Stap 21

Als er niet al eerder een hardware-bound ECDSA keypair voor gebruik in het Verifiable Credential was aangemaakt doet de app dit nu.

4.4.2.5.2.17 Stap 22

De App genereert een Proof of Possession van de public key gegenereerd in de vorige stap als per § 7.2.1.1 van OpenID4VCI, in de vorm van een JWS met daarin de volgende velden:

  • JWS header:
    • typ: MOET de waarde openid4vci-proof+jwt zijn.
    • alg: MOET de waarde ES256 zijn.
    • jwk: de ECDSA public key in JWK formaat (RFC 7517).
  • JWS body:
    • aud: MOET de Credential Issuer Identifier zijn, dat wil zeggen de URL die /.well-known/openid-credential-issuer host.
    • iat: Unix timestamp van het moment van creatie van deze JWS.
    • nonce: MOET de waarde van de c_nonce hebben die de App ontving in Stap 20.

Voorbeeld:

{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "nUWAoAv3XZith8E7i19OdaxOLYFOwM-Z2EuM02TirT4",
    "y": "HskHU8BjUi1U9Xqi7Swmj8gwAK_0xkcDjEW_71SosEY"
  }
}
.
{
  "aud": "https://issuer.example.com",
  "iat": 1701960444,
  "nonce": "LarRGSbmUPYtRYO6BQ4yn8"
}
4.4.2.5.2.18 Stap 23

De App genereert een nieuw ephemeral EC keypair voor encryptie. Deze wordt later door de Credential Issuer gebruikt in Stap 34 om het Verifiable Credential te versleutelen voordat hij naar de App verstuurd wordt.

4.4.2.5.2.19 Stap 24

De App genereert een nieuw DPoP JWS zoals in stap 11, middels hetzelfde EC keypair, met een vers willekeurig jti veld, en dit keer inclusief een ath veld in de JWS body, met als waarde de Base64url-encoding van de SHA256 hash van het access_token, dus schematisch BASE64URL(SHA256(access_token)).

Voorbeeld:

{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "x":" l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y": "9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv": "P-256"
  }
}
.
{
  "jti": "e1j3V_bKic8-LAEB",
  "htm": "POST",
  "htu": "https://issuer.example.org/credential",
  "iat": 1562262618,
  "ath": "LnCUSTkzMbG3p5Bw35U4EAOl-pXwcgOdhXxgK6CFYY4"
}
4.4.2.5.2.20 Stap 25

De App stuurt een Credential Request naar het Credential endpoint van de Credential Issuer als in § 7 van OpenID4VCI, middels een HTTP POST met de volgende HTTP headers:

  • Authorization: het access token met DPoP als authentication scheme.
  • DPoP: de DPoP JWS uit de vorige stap.

In de HTTP body verstuurt de App JSON-encoded een object met de volgende parameters:

  • proof: een object met daarin:
    • proof_type: MOET de waarde jwt hebben.
    • jwt: de JWS uit stap 22.
  • credential_response_encryption: een object dat aangeeft hoe de Credential Issuer het Verifiable Credential moet versleutelen voordat het naar de App gestuurd wordt, middels de volgende velden:
    • jwk: de public key gegenereerd in Stap 23.
    • alg: het asymmetrische encryptie-algoritme die de app verwacht. MOET de waarde ECDH-ES hebben.
    • enc: het symmetrische encryptie-algoritme die de app verwacht. MOET de waarde A128GCM, A192GCM, of A256GCM hebben.

Voorbeeld (newlines en whitespace enkel voor leesbaarheid):

POST /credential HTTP/1.1
Host: issuer.example.com
Content-Type: application/json
Authorization: DPoP JhbGciOiJSUzI1NiIsInR5
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik
 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR
 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE
 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj
 oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z
 WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RaNTNF
 c05yV0JiMHhXWG9hTnk1OUlpS0NBcWtzbVFFbyJ9.2oW9RP35yRqzhrtNP86L-Ey71E
 OptxRimPPToA1plemAgR6pxHF8y6-yqyVnmcw6Fy1dqd-jfxSYoMxhAJpLjA

{
  "proof": {
    "proof_type": "jwt",
    "jwt":
      "eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrI
      jp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiblVXQW9BdjNYWml0aDhFN2k
      xOU9kYXhPTFlGT3dNLVoyRXVNMDJUaXJUNCIsInkiOiJIc2tIVThCalVpMVU5WHFpN
      1N3bWo4Z3dBS18weGtjRGpFV183MVNvc0VZIn19.eyJhdWQiOiJodHRwczovL2NyZW
      RlbnRpYWwtaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNzAxOTYwNDQ0LCJub25j
      ZSI6IkxhclJHU2JtVVBZdFJZTzZCUTR5bjgifQ.-a3EDsxClUB4O3LeDD5DVGEnNMT
      01FCQW4P6-2-BNBqc_Zxf0Qw4CWayLEpqkAomlkLb9zioZoipdP-jvh1WlA"
  },
  "credential_response_encryption": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "gUOuh9dfi-44HT-2YL5HdEZ9opP_ItHrpp28JtQyaOY",
      "y": "0UOvHfidVyKFN4gDz9bIstU0o0qWCaZrRaVhplgkm58"
    },
    "alg": "ECDH-ES",
    "enc": "A128GCM"
  }
}
4.4.2.5.2.21 Stap 26 en 27

De Credential Issuer haalt middels het access token het BSN van de gebruiker, de c_nonce en de DPoP public key op.

4.4.2.5.2.22 Stap 28

De Credential Issuer verifieert de DPoP JWS uit de DPoP HTTP header net als in stap 16, dit keer met de volgende extra checks:

  • de DPoP JWS MOET een ath veld hebben met daarin de Base64url-encoding van de SHA256 hash van het access token;
  • de public key in het JWK veld MOET gelijk zijn aan degene die de Credential Issuer aantrof in stap 16.
4.4.2.5.2.23 Stap 29

De Credential Issuer verifieert de Proof of Possession in het jwt veld in het proof object van de Credential Response als volgt.

  1. Parseer de JWS header (nog zonder de JWS geverifieerd te hebben).
  2. Controleer dat het typ veld in de JWS header de waarde openid4vci-proof+jwt bevat.
  3. Controleer dat het alg veld in de JWS header de waarde ES256 bevat.
  4. Controleer dat het jwk veld in de JWS header een object bevat die een P-256 public key is geëncodeerd als JWK, en dat dit object niet een d veld (een private key) in zich heeft.
  5. Verifieer de JWS tegen de public key uit bovenstaande stap.
  6. Controleer dat het aud veld in de JWS body de Credential Issuer Identifier bevat (de URL die /.well-known/openid-credential-issuer host).
  7. Controleer dat de JWS volgens het iat veld in de JWS body niet ouder is dan een bepaalde grens, bijvoorbeeld 60 seconden.
  8. Controleer dat de nonce in de JWS body gelijk is aan de c_nonce die in Stap 20 aan de App is verstrekt.
4.4.2.5.2.24 Stap 30 en 31

Middels het BSN worden de gegevens van de eindgebruiker die geïssued moeten worden als attributen in het Verifiable Credential opgehaald uit de BRP.

4.4.2.5.2.25 Stap 32

De Credential Issuer tekent met zijn private key het Verifiable Credential, in de vorm van een JWS. Hierbij plaatst hij de public key in het jwk veld van het Proof of Possession (zie Stap 29) in het cnf veld van de Verifiable Credential JWS. Zie de Verifiable Credentials sectie hierboven voor alle velden en een voorbeeld.

4.4.2.5.2.26 Stap 33

De Credential Issuer maakt het Credential Response, een JSON object met daarin enkel een credential veld met als waarde de JWS uit de vorige stap:

{
  "credential": "eyBRa..."
}

De Credential Issuer versleutelt dit object in de vorm van een JWE naar de public key in het jwk veld in het credential_response_encryption object in het Credential Request uit Stap 25.

4.4.2.5.2.27 Stap 34

De Credential Issuer verstuurt bovenstaand JWE naar de App.

4.4.2.5.2.28 Stap 35

De App controleert dat het Credential Response versleuteld in de vorm van een JWE is, en breekt af zoniet. Hij ontsleutelt de JWE met de private key gegenereerd in Stap 23, parseert de inhoud van de JWE als JSON object, en vindt daarin het Verifiable Credential in het credential veld.

4.4.2.5.2.29 Stap 36

De App verifieert het Verifiable Credential tegen de public key van de Credential Issuer, eventueel gebruik makend van het kid veld in de JWS header om de juiste public key te identificeren.

4.5 Revocatie

Elke participant in het stelsel (App, Issuer, Verifier) gebruikt een public/private keypair tijdens interacties met andere partijen: Apps authenticeren zich naar Verifiers middels een public/private keypair, net als omgekeerd, en Issuers gebruiken een public/private keypair om Verifiable Credentials naar Apps te issuen. In bepaalde gevallen, bijvoorbeeld wanneer een private key lekt, of gelekt zou kunnen zijn, of wanneer een participant zich misdraagt, moet het public/private keypair van die partij kunnen worden teruggetrokken. Dit proces heet revocatie. Revocatie (terugtrekken) heeft dus als doel om ervoor te zorgen dat de eigenaar van een public-private keypair deze niet meer kan gebruiken.

Hoe het terugtrekken van een public-private keypair in zijn werk gaat hangt af van hoe het keypair bekend is in het stelsel.

De volgende tabel vat bovenstaande samen.

Participant Public key staat in Revocatie gespecificeerd in Revocatietechniek
App Verifiable Credential Blauwe Knop Connect Token Status List
Credential Issuer Stelseldocument Toepassingsprofiel [Bepaald in toepassingsprofiel]
Verifier Stelseldocument Toepassingsprofiel [Bepaald in toepassingsprofiel]

4.5.1 Revocatie van App Verifiable Credentials

Deze sectie specificeert revocatie voor Apps. Omdat de public key van een App altijd als onderdeel van een Verifiable Credential wordt gecommuniceerd aan de Verifier, moet het Verifiable Credential in zijn geheel kunnen worden teruggetrokken. In deze specificatie gebruiken we daarvoor de Token Status List standaard.

4.5.1.1 Terminologie

Dezelfde terminologie als in de Terminologie sectie, met daaraan toegevoegd:

  • Revocatie: het ongeldig verklaren van een Verifiable Credential.
  • Terugtrekken: synoniem van revocatie.
  • TSL: afkorting van Token Status List.
  • Alles in de "Terminology" sectie in de TSL standaard, in het bijzonder:
    • Token: een digitaal ondertekende datastructuur, zoals een JWS.
    • Referenced Token: een Token die teruggetrokken kan worden middels de TSL standaard; in de context van deze standaard altijd een Verifiable Credential.
4.5.1.2 Token Status List

Voor revocatie van Verifiable Credentials maakt deze standaard gebruik van (draft 12 van) de Token Status List standaard. Deze standaard combineert schaalbaarheid wanneer het aantal uitgegeven Verifiable Credentials groot is met privacy van de eindgebruiker van de App, in de zin dat wanneer een Verifier bij ontvangst van een Verifiable Credential controleert dat deze niet is teruggetrokken de Issuer van het Credential niet leert om welk specifiek Credential het gaat. De standaard bereikt dat als volgt:

  1. De status van elk Verifiable Credential wordt gerepresenteerd als een enkele bit: 0 (niet teruggetrokken) en 1 (teruggetrokken).
  2. De Credential Issuer maakt een lijst van bits, in eerste instantie allemaal met waarde 0. De Credential Issuer comprimeert deze lijst met zlib en plaats daar een digitale handtekening over. De (gecomprimeerde) lijst heet een Status List, en de ondertekende gecomprimeerde lijst wordt een Status List Token genoemd. De Credential Issuer plaatst het Status List Token online onder een specifieke publieke URL. (Een Status List kan groot zijn, met de bits van duizenden of zelfs miljoenen Verifiable Credentials daarin, maar omdat doorgaans de meeste Verifiable Credentials nooit worden teruggetrokken is de zlib compressie erg effectief in het onder controle houden van de grootte van de data.)
  3. Bij uitgifte van een Verifiable Credential kiest de Issuer een index in de Status List die hij niet eerder heeft gekozen bij uitgifte van eerdere Verifiable Credentials. De Issuer slaat deze index op in zijn database, en neemt het volgende op in de body van het Verifiable Credential:
    "status": {
      "status_list": {
        "idx": 42,                                  // De gekozen index
        "uri": "https://example.com/statuslists/1"  // URL naar de Status List Token
      }
    }
    
  4. Wanneer een Verifier een Verifiable Credential ontvangt, handelt hij als volgt om vast te stellen of het Credential teruggetrokken is:
    1. Hij verifieert de Verifiable Credential zoals normaal, en parseert de body daarvan inclusief bovenstaand JSON object.
    2. Hij haalt de Status List Token op vanaf de uri in het status_list object, of uit een lokale cache wanneer hij de betreffende Status List recent eerder heeft opgehaald, verifieert de handtekening van de Issuer, en decomprimeert hem.
    3. Als de bit op de positie aangegeven door idx in de Status List op 1 staat is het Credential teruggetrokken. Als de bit op 0 staat is hij niet teruggetrokken.
  5. Wanneer een issuer een Verifiable Credential wil terugtrekken zoekt hij de index op in zijn database die hij gebruikt heeft bij uitgifte van het Verifiable Credential. In de Status List zet hij de bit op die index op 1. Vervolgens comprimeert en tekent de Issuer de (geüpdate) Status List en plaatst deze online op de juiste uri.
  6. Wanneer alle bits in de Status List zijn toegewezen aan eerder uitgegeven Verifiable Credentials maakt de Verifier een nieuwe Status List als in stap 2, kiest daarvoor een nieuwe URL (bijvoorbeeld https://example.com/statuslists/2), en gebruikt in het vervolg deze nieuwe Status List bij het uitgeven van Verifiable Credentials (totdat ook deze lijst op is).

Voor een uitgebreidere introductie, zie de "Introduction" sectie van de Token Status List standaard.

Visuele weergave van een Status List
Figuur 17 Visuele weergave van een Status List

NB: In de Token Status List standaard is het mogelijk om meer dan twee statussen (teruggetrokken of niet) toe te kennen aan Verifiable Credentials. Een derde status zou bijvoorbeeld "suspended" kunnen zijn, wat betekent dat de Credential tijdelijk ongeldig zodanig dat deze status later weer ongedaan gemaakt kan worden, zodat het Credential dan weer geldig is. In dit geval gebruikt ieder Credential niet 1 maar 2 of meer bits in de Status List, afhankelijk van hoeveel mogelijke statussen er zijn. In deze standaard maken we geen gebruik van deze mogelijkheid. Een Credential is dus ofwel teruggetroken ofwel niet, en elke bit op de Status List correspondeert met de status van één Verifiable Credential.

4.5.1.3 TSL implementatieprofiel

De TSL standaard biedt op een aantal plekken verschillende opties aan. In deze standaard maken we daarin de volgende keuzes.

  1. Er wordt 1 bit per Verifiable Credential gebruikt in de Status List, en de twee mogelijke statussen zijn dus teruggetrokken of niet.
  2. De TSL standaard maakt onderscheid tussen de Credential Issuer en de partij die de Status List Token ondertekent en beheert, en maakt het daarmee mogelijk dat het uitgeven van Verifiable Credentials het terugtrekken ervan door verschillende partijen worden gedaan. In deze standaard MOET de Credential Issuer ook de uitgever en beheerder zijn van de Status List Token. Wel MAG de Status Provider, de partij die het HTTP endpoint beschikbaar stelt waaronder de Status List Token is gepubliceerd, een andere partij zijn dan de Credential Issuer (zoals bijvoorbeeld een CDN).
  3. De Status List Token moet volgens de TSL standaard digitaal ondertekend worden door (in dit geval) de Issuer met een private key, zodat gebruikers de authenticiteit van de Status List Token kunnen vaststellen bij gebruik met de corresponderende public key. Deze private key MOET NIET dezelfde zijn als degene waarmee de Issuer de Verifiable Credentials uitgeeft, en MOET dus een speciale private key voor dit doel zijn. Hoe gebruikers de corresponderende public key kunnen ontdekken MOET gespecificeerd worden in een toepassingsprofiel.

    Voorbeeld: in Vorderingenoverzicht Rijk is het stelseldocument een JSON datastructuur waarin alle Credential Issuers en Verifiers staan gespecificeerd als JSON objecten. Zoals gespecificeerd in sectie "Keys in het scheme" van het Vorderingenoverzicht Rijk toepassingsprofiel bevat elk JSON object die een Issuer beschrijft een veld genaamd revocationPublicKey, welke de public key(s) bevat waarmee de Issuer de Status List Token ondertekent.

  4. De Status List Token MOET getekend worden met een van de algoritmes gespecificeerd in de Digitale Handtekeningen sectie.
  5. De Status List Token MOET in JWT formaat geëncodeerd worden (het CWT formaat, welke de TSL standaard ook toestaat, wordt dus niet ondersteund).
  6. Elke Status List van de Credential Issuer MOET ruimte bieden voor minimaal 100.000 indices. Groter MAG: hoe groter, hoe beter voor de privacy van de eindgebruiker. (Zie de Size comparison appendix van de TSL standaard voor een indicatie van hoe de grootte van de Status List Token afhangt van hoeveel indices hij heeft.)
  7. Bij uitgifte van een Verifiable Credential MOET de Credential Issuer de index in de Status List die hij gebruikt kiezen willekeurig kiezen (en dus niet bijvoorbeeld sequentieel). De Issuer MOET NIET een eerder gebruikte index in de lijst kiezen.
  8. De Status List Token MOET een ttl veld bevatten welke aangeeft hoelang (in seconden) gebruikers de lijst mogen cachen nadat ze hem hebben ontvangen. Hiervoor geldt het volgende:
    1. Gebruikers van de lijst MOETEN de lijst cachen zolang als het ttl veld aangeeft, voordat ze het endpoint waarop de Status List Token gehost wordt opnieuw aanroepen.
    2. Wanneer een gebruiker een Status List Token uit zijn cache raadpleegt waarvan de ttl verlopen blijkt te zijn MOET de gebruiker de Status List Token opnieuw downloaden.
  9. Een Status List Token MOET een exp veld bevatten welke aangeeft wanneer de geldigheid van het Token verloopt. (Hoe lang de Status List Token geldig is, dus het verschil tussen exp en iat, mag een stuk groter zijn dan het ttl veld.)
  10. Voor het HTTP request waarmee een Status List Token wordt opgehaald geldt het volgende:
    1. De HTTP client MOET de Accept: application/statuslist+jwt HTTP header gebruiken.
    2. De HTTP server MOET de Content-Type: application/statuslist+jwt HTTP header gebruiken.
    3. De HTTP server MOET voor de response gzip Content-Encoding als in RFC9110 gebruiken.
  11. De "Historical resolution" functie van de TSL standaard MOET NIET worden gebruikt. Wanneer een HTTP client de time query parameter meelevert in het request bij het ophalen van de Status List Token MOET de HTTP server antwoorden met HTTP 501 (Not Implemented).

4.6 Key validatie

Elke participant in het stelsel (App, Issuer, Verifier) gebruikt een public/private keypair tijdens interacties met andere partijen: Apps authenticeren zich naar Verifiers middels een public/private keypair, net als omgekeerd, en Issuers gebruiken een public/private keypair om Verifiable Credentials naar Apps te issuen. In deze sectie specificeren we hoe public keys moeten worden gevalideerd voor gebruik.

Elke public key MOET een verloopdatum hebben: een datum waarna hij als niet meer geldig moet worden beschouwd.

Voordat een public key van een participant gebruikt wordt voor wat dan ook wordt MOET gevalideerd worden dat deze geldig is. Als deze validatie faalt MOET de public key NIET worden gebruikt.

4.6.1 Key validatie voor Verifiers en Verifiable Credentials

Op het moment van gebruik van de public key:

  • Controleer dat de verloopdatum van de key in de toekomst ligt.
  • Controleer dat de key niet is teruggetrokken.

Voor Verifiable Credentials kunnen deze validaties respectievelijk worden gedaan middels het exp veld in het Verifiable Credential, en middels de TSL standaard zoals gespecificeerd in de "Revocatie" sectie.

Zoals eerder beschreven specificeert het toepassingsprofiel hoe de verloopdatum en revocatie van public keys wordt opgenomen in het stelseldocument. Hoe deze checks moeten gebeuren voor Verifier public keys hangt daarvan af.

4.6.2 Validatie van Issuer keys tijdens verificatie van Verifiable Credentials

De uitzondering op bovenstaande regels is wanneer een public key van een Credential Issuer wordt gebruikt tijdens verificatie van een Verifiable Credential. In dit geval MOET de Issuer public key niet zoals hierboven beschreven maar als volgt worden gevalideerd:

  • Controleer dat de public key van de Issuer niet verlopen was, op het moment van uitgifte van het Verifiable Credential (welke in het iat veld van het Verifiable Credential staat).
  • Controleer dat de key niet is teruggetrokken, op dit moment.

Op deze manier kan een Issuer Verifiable Credentials blijven uitgeven tot aan het moment dat zijn key verloopt.

5. Lijst met figuren

6. Conformiteit

Naast onderdelen die als niet normatief gemarkeerd zijn, zijn ook alle diagrammen, voorbeelden, en noten in dit document niet normatief. Verder is alles in dit document normatief.

De trefwoorden MAG, MOET, MOET NIET, MOETEN en MOGEN in dit document moeten worden geïnterpreteerd als in BCP 14 [RFC2119] [RFC8174] als, en alleen als deze in hoofdletters zijn weergegeven, zoals hier getoond.

A. Referenties

A.1 Normatieve referenties

[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
Overheidsbrede Standaard - Werkversie