Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Op basis van gedefinieerde toegangsregels kan al dan niet toegang verleend worden aan een Client Application (applicatie instantie) die daar om verzoekt. Hierbij worden achtereenvolgens de volgende stappen doorlopen:

...

  1. De client (applicatie-instantie) MOET zich (dynamisch) registreren om voor elke instantie een afzonderlijke en unieke "Client_ID" te verkrijgen (zie stappen 1 en 2). Client registratie KAN worden voltooid door ofwel statische configuratie (out-of-band, via een beheerder, etc.) of dynamisch. De client (applicatie-instantie) MOET een unieke publieke en geheime sleutelpaar genereren, en de jwks_uri (referentie naar de sleutelpaar) of publieke sleutelwaarde registreren bij de Autorisatie Server registreren. Zie RFC-7517.
  2. Het verkrijgen van een toegangstoken door een token verzoek te sturen naar de Autorisatie Server, die het verzoek van de consument verifieert met behulp van een JWT (JSON Web Token) of identiteitsbewijs (zie stappen 3 en 4)
  3. Zodra de client (applicatie-instantie) het toegangstoken verkregen heeft kan deze (her)gebruikt worden, tot het toegangstoken verlopen is, voor elke serviceverzoek aan de FHIR Resource Provider (zie stappen 5 en 6). Nadat het toegangstoken verlopen is, moet men opnieuw een toegangstoken opvragen. 

De URL's gebruikt in de PoC:

Client (Applicatie)

...

Autorisatie Server Interface

  1. Metadata van de Autorisatie Server is via publiek internet benaderbaar. Metadata kan conform RFC-8414 worden opgehaald, op een bekende URL, die herleid kan worden m.b.v. de 'iss' claim uit het token (zie ook section-3.1 van RFC8414)
  2. De Authorization Server Metadata Response bevat o.a. de volgende attributen:
    1. issuer;
    2. token_endpoint;
    3. token_endpoint_auth_signing_alg_values_supported;
    4. jwks_uri;
    5. scopes_supported

...

CapabilityStatement (eHealth Mogelijkheden) - [review]

TOP-KT-016 - SMART on FHIR Conformiteit [review]


JWKS

De public key waarmee de digitale handtekening kan worden gecontroleerd wordt conform RFC-7517, als een JWK beschikbaar gesteld. De URL van waarop de JWK Set kan worden opgevraagd (jwks_uri) maakt deel uit van de Autorisatie Server metadata response. 
Iedere JSON Web Key (JWK) in de set, die beschikbaar wordt gesteld op de jwks_uri, bevat een 'kid' parameter. De juiste JWK in de JWK Set wordt gevonden o.b.v. de waarde van het 'kid' attribuut in de header van de ontvangen JWT.

...

Code Block
languagejs
titleVoorbeeld: /.well-known/jwks.json
{
  "keys": [
    {
      "kty": "RSA",
      "kid":"lhqSXMVFn8AFG2",
      "use":"sig",
      "n":"prv1Rj9R2tpdun4IuOulqKerjAX9MEsxMpYvVobh_AbkS",
      "e":"AQB"
    }, {
      "kty": "RSA",
      "kid":"lhqSXMVFn8AFG3",
      "use":"sig",
      "n":"kwa83hj9R2tp6doqIuOulqKeruJa4MEsxMpYvVjee_dh5",
      "e":"AQB"
    }
    ]
}


 Client Registratie (stap 1, 1.1 en 2)

Voor Koppeltaal is een Proof of Concept gebouwd om een client (applicatie-instantie) te registreren en een client_id te ontvangen. Zie SMART Service Registratie (headease.nl). Hier kan een client een aanvraag indienen en een jwks_uri (jwks endpoint) of een publieke sleutel opvoeren, zodat deze op elk moment door de Autorisatie Server gevalideerd en geverifieert kan worden. Na registratie krijgt de client een uniek client_id toegewezen, de client_id moet door de client beschermt worden en kan vervolgens in het identiteitsbewijs (gesigneerde JWT), bij stap 3, gebruikt worden.

...

BELANGRIJK: In bovenstaand voorbeeld willen we kunnen zoeken op Device.resource-origineorigin. In bovenstaand voorbeeld op "AutorisatieServer_id". Indien we naar de (huidige) zoekparameters van Device kijken, is er geen parameter gedefinieerd die deze extensie selecteert. Hiervoor moet een nieuwe searchParameter worden gedefinieerd. Alleen de FHIR (Resource) Provider MOET automatisch een SearchParameter toevoegen voor deze extensie, als deze nog niet bestaat. De extensie meegeven op een POST MOET in een foutmelding resulteren. De extensie MOET altijd mag meegegeven worden op een PUT en mag dan NIET aangepast worden. Als de resource-origin niet aanwezig is in de PUT, dan zal KT deze zelf toevoegen. Indien er een aanpassing op de extensie wordt uitgevoerd resulteert dit in een foutmelding. 

...

De volgende paragraaf laat zien hoe men een (RSA) sleutelpaar in PKCS8 tekst formaat met sleutellengte 2048 kan aanmaken, voor het onderteken van JWT en uitwisselen van publieke sleutel. Zie ook: https://github.com/Koppeltaal/Koppeltaal-2.0-Generate-KeyPair.

Het aanmaken van sleutelparen


BELANGRIJK:

  • De ondertekening MOET gebruik maken van een asymmetrisch algoritme, en een asymmetrische (RSA) sleutelpaar
  • De validerende partij MOET de volgende asymmetrische algoritmen accepteren (zie [RFC-7518] - 3.1):
    • RS256 (Aanbevolen), RS384 (Optioneel) en RS512 (Optioneel)
    • ES256 (Aanbevolen), ES384 (Optioneel)en ES512 (Optioneel)
  • Bij de aanbevolen asymmetrische algoritme MOET een sleutel van 2048 bits of groter worden gebruikt.

...

  1. Genereer een RSA geheime sleutel met een lengte van 2048 en sla dit op in een bestand 'key.pem':

    Code Block
    languagetext
    titleGeheime sleutel genereren
    $ openssl genrsa -out key.pem 2048
    Generating RSA private key, 2048 bit long modulus
    ..........+++
    ..........................................................................+++
    e is 65537 (0x10001)
    
    


  2. Extraheer de publieke sleutel uit het sleutelpaar en sla dit op in 'public.pem':

    Code Block
    languagetext
    titlePublieke sleutel extractie
     $ openssl rsa -in key.pem -outform PEM -pubout -out public.pem
    writing RSA key


    Info
    Wanneer een asymmetrisch (RSA) sleutelpaar wordt gegenereerd, 
    bewaar de geheime sleutel op een veilige plek (bv een KeyStore - kluis)
    op een systeem dat als veilig beschouwd wordt.


  3. Geheime sleutels worden op een PKCS8 (Public-Key Cryptography Standards) beheerd en bewaard. Dit formaat wordt bij alle algoritmes gebruikt en is niet alleen voor RSA sleutels bedoeld. PKCS8 is de standaard om geheime sleutel gegevens op te slaan en te beheren.
  4. Converteer RSA geheime sleutel naar PKCS8 in tekst formaat en sla dit op in 'pk8key.pem':

    Code Block
    languagetext
    titleGeheime sleutel naar PKCS8 converteren
    $ openssl pkcs8 -in key.pem -topk8 -nocrypt -out pk8key.pem
    

    Voor verdere detail specificaties over PKCS8 verwijzen we naar RFC-5208.

Het aanmaken van een JSON Web Signature (JWS - client identiteitsbewijs  - voorwerk voor stap 3)

Met een JSON Web Signature (JWS - client identiteitsbewijs) kan men een toegangstoken opvragen bij de Autorisatie Server. De client MOET in staat zijn om een JWS te genereren, zoals beschreven in RFC-7515. Voor de PoC in Koppeltaal 2.0 ondersteunt de client RS512 voor de JSON Web Algoritme (JWA) header parameter, zoals vastgelegd in RFC-7518. De Autorisatie Server moet in staat zijn, voor de PoC, de signature (handtekening) te valideren met RS512.

...

Authenticatie JWT Header waarden
algvereistRS512
typvereistVaste waarde: JWT.
kidoptioneelHier wordt aangegeven welke sleutel is gebruikt om de JWS te beveiligen. Met deze parameter kan de initiator expliciet een sleutelwijziging signaleren naar de ontvanger


Authenticatie JWT Claims
issvereistIssuer of uitgever van de JWT - de client_id van de client, zoals bepaald tijdens de registratie bij de Autorisatie Server.
subvereist

De (technische) identifier van de gebruiker. Bij een applicatie is dit de client_id van de client, zoals bepaald tijdens de registratie bij de Autorisatie Server. Bij het launchen van een applicatie, wordt de identifier van een persoon gebruikt die de lancering uitvoert.  Op deze manier kunnen toepassingen begrijpen wie de opgegeven taak start. Bijvoorbeeld Patient/123456789.

audvereistDe Autorisatie Server "token URL" (De zelfde URL waar de JWT naar gestuurd wordt, zie volgend voorbeeld).
iatvereistTijdstempel voor wanneer de JWT is aangemaakt.
expvereistVerlooptijdstip voor verificatie van de JWT, uitgedrukt in seconden sinds het "tijdvak" (1970-01-01T00:00:00Z UTC). Deze tijd MAG in de toekomst niet meer dan vijf minuten duren.
jtivereistEen nonce-tekenreekswaarde die deze verificatie-JWT uniek identificeert.

...

Hier moet men de geheime sleutel als PKCS8 formaat opvoeren. De geheime sleutel wordt NIET bij de testsuite opgeslagen of bewaard.

Toegangstoken opvragen (stap 3 en 4)

Indien de client een JWS heeft gegeneerd, zoals beschreven on voorgaande, kan de client m.b.v. de aangemaakte JWS een toegangstoken aanvragen, door de aanvraag te posten naar het tokenEndpoint van de Autorisatie Server (zie het veld "aud" in de JWT claim),  met behulp van content-type application/ x-www-form-urlencoded met de volgende parameters: 

...

Parameters
scopeoptioneelDe scoop of omvang van de gevraagde toegang. Zie opmerkingen over de "scope"verderop.
grant_typevereistVaste waarde: client_credentials.
client_assertion_typevereistVaste waarde:urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
client_assertionvereistDe JWS bestaat uit de drie Base64-URL-reeksen: header, payload en signature, gescheiden door punten.

Stap 3

Code Block
languageactionscript3
titlePost (ClientCredentials als Client Secret JWT)
POST https://authentication-service.koppeltaal.headease.nl/oauth2/token
Accept: application/json 
Content-Type: application/x-www-form-urlencoded 

grant_type=client_credentials  
&scope=system%2FActivityDefinition.*
&client_assertion=eyJn0.MdIBDor2Bsq5ge51EkWajzZ7AL.isVp-bskzUsqUf77ejqX_CBAqkNdH1Zebn93  <fictief encoded JWS voorbeeld>
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer 

...

  • De Autorisatie Server antwoordt op de volgende manier en retourneert een toegangstoken voor de client
  • De toegangstoken is een JSON Web Token(!) en kan men decoderen

Stap 4

Code Block
languagejs
titleAccessToken
{
  "access_token":"eyJraWQiOiJ1N.eyJhenDdiJteS1j.qBPcaQRD6qAGFEqipmfBA", <fictief encoded JWS voorbeeld>
  "token_type":"Bearer",
  "expires_in":3600,
  "refresh_token":"e0c248e-30ee-4667-8eb4-4cfebe15a351",    
  "scope":"system/ActivityDefinition.*"
}

Scope

De scope bestaat uit de volgende onderdelen:

  • Resource context. Een (gebruikers) context waarin rechten worden aangevraagd: user (een geauthentiseerde gebruiker), patiënt (beperkt tot een geïdentificeerde patiënt) of system  (geauthentiseerd systeem)
  • Resource type. Een FHIR resource type, die bij naam benoemd wordt
  • Rechten. Rechten die met lezen (ook historische gegevens) en/of schrijven (ook het verwijderen van gegevens) te maken hebben op een instantie van een resource . '*' is lezen en schrijven.

...

  • .


Service (interactie met FHIR Resource Provider) (stap 5 en 6)

Merk op dat bij een RESTful-framework alle interacties rechtstreeks op de FHIR Resource Provider worden uitgevoerd met behulp van het HTTP protocol (POST, PUT, GET en DELETE). De API (interface) heeft geen directe betrekking op authenticatie, autorisatie en controle. Hiervoor gebruiken we het toegangstoken (access_token) die we in de autorisatie (Authorization) header opnemen bij elk service verzoekbericht (interactie), zie stap 5. Het service verzoekbericht kan goedgekeurd worden en dan krijgt de client informatie terug over het verzoek of het verzoek kan afgewezen worden, en dan krijgt de client informatie terug waarom het is afgewezen.

Toegangstoken management en refresh tokens

Zoals ook in het "AccessToken" voorbeeld al gebruikt wordt, wordt aanbevolen om het toegangstoken (access_token) 3600 seconden, oftewel één uur te laten gelden (zie ook expires_in ). Dit betekent dat na één uur het toegangstoken NIET meer gebruikt kan worden, voor een service verzoekbericht. In OAuth2 MAG de client het toegangstoken zelf NIET vernieuwen. Daarom MOET, zodra de client de melding krijgt dat het toegangstoken verlopen is (Token Expired Error), een nieuw toegangstoken aanvragen. Hiervoor kan de client, de "Client Credential Flow" opnieuw doorlopen of, als de client in bezit is van een refresh_token die bij het verlopen toegangstoken hoort, een nieuw refresh_token verzoek indienen, om zo een nieuw toegangstoken en een refresh token te verkrijgen.

...

  • de autorisatie server het refresh_token kan hebben ingetrokken
  • het refresh_token verlopen is
  • de beleidsregels omtrent de toegang tot de resources zijn gewijzigd
Refresh token verzoek
Code Block
languageactionscript3
titlePost (Refresh token verzoek)
POST https://authentication-service.koppeltaal.headease.nl/oauth2/token
Accept: application/json 
Content-Type: application/x-www-form-urlencoded 

grant_type=refresh_token  
&scope=* <optioneel>
&refresh_token=e0c248e-30ee-4667-8eb4-4cfebe15a351  <fictief refresh token voorbeeld>
Response
Code Block
languagejs
titleAccessToken
{
  "access_token":"eyJrbWQiOiK1N.eyJhebDdiDteS2j.qBPcbQRD6eAGFEqilmCB", <fictief encoded JWS voorbeeld>
  "token_type":"Bearer",
  "expires_in":3600,
  "refresh_token":"e0c248e-21de-5267-8eb4-4cfebe16b385"
}

...