Beschrijving
Binnen Koppeltaal krijgt elke applicatie-instantie (een applicatie binnen een domein) een rol toegekend. Deze rol bepaalt welke acties uitgevoerd mogen worden op de FHIR resource service.
Overwegingen
Een domein bevat meerdere applicatie-instanties. Lang niet altijd zullen alle applicaties in een domein data van elkaar gebruiken. Vanwege het privacy-by-design principe mogen applicaties geen onnodige resources opvragen. Dit moet zo min mogelijk impact hebben op de eindgebruikers. Zo is de FHIR resource service bijvoorbeeld verantwoordelijk voor het filteren van informatie op een “GET all”-request.
Helaas is er binnen FHIR geen gestandaardiseerde manier om dit op te lossen. Het staat dienstverleners vrij om een gepast autorisatiemodel toe te passen. Als oplossing hiervoor is een Role Based Access Control (verder: RBAC) autorisatiemodel ontwikkeld. Deze oplossing moet goed passen op de brede set aan functionaliteiten die de FHIR http en search specificaties bieden.
Toepassing en restricties
Autorisatiemodel
Kernpunten
Als oplossing is een RBAC autorisatiemodel tot stand gekomen middels deze vier uitgangspunten:
- Registreren: Bij het toetreden van een domein wordt voor elke applicatie-instantie een
Device
resource aangemaakt. - Authenticeren: Alle communicatie met de FHIR resource service vereist een
access_token
. Dit token bevat (indirect) informatie over welkeDevice
dit request uitvoert. - Eigenaarschap: Alle resources die aangemaakt worden op de FHIR resource service, krijgen automatisch een
resource-origin
extensie. Deze extensie refereert naar de gekoppeldeDevice
resource van de geauthenticeerde applicatie-instantie. - Autoriseren: Alle CRUD-acties die plaatsvinden op een resource, worden - aan de hand van de
resource-origin
extensie en de rol van de geauthenticeerde applicatie-instantie - geautoriseerd.
Rollen en permissies
Het autorisatiemodel is een op RBAC-gebaseerd model. Een applicatie-instantie krijgt maximaal één rol toegekend vanuit het domeinbeheer stelselcomponent. Deze rol is gekoppeld aan een set van permissies. Elke permissie bevat de volgende informatie:
Resource: Een permissie is altijd gekoppeld aan een enkele FHIR Domain Resource.
Actie: Is van toepassing op een Create (C), Read (R), Update (U) of Delete (D) actie.
Scope: Heeft één van de volgende scopes:
Scope Beschrijving OWN De permissie is enkel van toepassing op resources waarvan de resource-origin
overeenkomt met de geauthenticeerde applicatie-instantie.GRANTED De permissie is van toepassing op resources waarvan de resource-origin
overeenkomt met één van de geselecteerde applicatie-instantie(s).ALL De permissie is van toepassing op alle resources in het domein.
Registreren van Devices
Wanneer een applicatie een domein toetreedt, krijgt deze applicatie-instantie een client_id
toegekend. Het domeinbeheer stelselcomponent heeft de verantwoordelijkheid om een Device
resource aan te maken op de FHIR resource service. Deze Device
MOET de volgende identifier
bevatten:
{
"system": "<https://koppeltaal.nl/client_id>",
"value": "<CLIENT_ID>"
}
Mappen van access_token
naar Device
Wanneer een access_token
opgehaald wordt door een applicatie-instantie, MOET deze altijd het azp
veld bevatten. Dit veld wordt door de autorisatieserver gevuld met de client_id
van de applicatie die de access_token
opvraagt. Aangezien elke Device
resource een https://koppeltaal.nl/client_id
identifier moet hebben, kan de mapping plaatsvinden.
Rollen en permissies van Domeinbeheer naar authorizatie server
Het domeinbeheer stelselcomponent beheert de rollen en bijbehorende permissies. Deze permissies kunnen op twee manieren doorgegeven worden:
- Domeinbeheer biedt de mapping aan middels een API call.
- Domeinbeheer schrijft de records weg in een gedeelde cache/database met de auth server.
Deze laatste oplossing heeft de voorkeur aangezien deze over het algemeen beter te beveiligen is.
Permissies zetten op access_token.scope
Bij het uitgeven van een access_token
MOET de autorisatieserver de gekoppelde permissies omzetten naar het scope
veld. Raadpleeg [TODO: LINK TOEVOEGEN] voor de exacte uitwerking hiervan.
Toekennen resource-origin
aan resources
De FHIR resource service MOET voor elke Resource
die aangemaakt worden de resource-origin
extensie toevoegen. Op deze manier is per Resource
altijd te achterhalen wat het bronsysteem is van deze Resource
. Koppeltaal maakt expliciet gebruik van deze extensie aangezien er een Reference
naar een Device
dient te zijn. FHIR zelf heeft het Resource.meta.source
veld. Echter is deze van het type URI, en daarom te ambigu voor dit doeleinde.
De applicatie-instantie mag de resource-origin
extensie NIET zelf zetten op een POST
. De resource-origin
MAG wel meegegeven worden aan een PUT
. In dit geval MOET de FHIR resource server valideren dat deze ongewijzigd is. Indien de resource-origin
extensie NIET gezet is in een PUT
, MOET de FHIR resource service deze zetten.
Autoriseren
Voor het autoriseren wordt gebruik gemaakt van de V2 scopes uit de SMART app launch. De uitgegeven scopes zijn een subset van de V2 scopes, en hebben altijd de resource-origin
parameters. Daarnaast heeft ons RBAC-model geen s
permissie. Deze wordt expliciet gezet door de auth server wanneer de client een r
permissie heeft. De volgende syntax wordt gehanteerd:
De value van de resource-origin
parameter is altijd een comma-separated lijst van logical Device
ids. In het geval van een GRANTED permissie kunnen hier dus meerdere waarden staan.
De FHIR resource service autoriseert elke binnenkomende CRUD request. Elke request MOET minimaal de volgende logica uitvoeren voor de autorisatie:
Wanneer een request binnenkomt kan de volgende informatie opgehaald worden:
Informatie Hoe op te halen <resource_type> Dit kan bepaald worden aan de hand van de URL. De eerste waarde na de slash van de base FHIR resource service bevat altijd het Resource type. Bijvoorbeeld /Patient
,/Patient/2
of/ActivityDefinition
<action> Dit wordt bepaald aan de hand van het type HTTP request. GET → Read, POST → Create, PUT → Update en DELETE → Delete <resource-origin> Indien de request geen Create betreft, gaat het altijd om bestaande resources. Deze hebben per definitie een resource-origin
extensie die aangeeft wie de eigenaar van de resource is. Deze waarde MOET uit de gepersisteerde entiteit(en) gehaald worden. Wanneer een entiteit geüpdatet wordt, wordt deresource-origin
waarde dus van de te updaten versie afgehaald.- Indien de <action> een create is:
- hoeft de
resource-origin
niet geverifieerd te worden. Deze mag niet zelf gezet worden, maar wordt automatisch gezet door de FHIR resource service. Daarnaast is een create permissie altijd in de context van de OWN permissie. Het is niet toegestaan om Resources namens een andere applicatie aan te maken. - Zoek een scope in de context van
<resource_type>
of*
(all) EN action met letterlijke tekstc
of*
.Bijvoorbeeld bij een create van een
Patient
zijn de volgende scopes valide (in de onderstaande voorbeelden is de logical id van deresource-origin 3a2c98b5-298e-4f95-ab21-077d6b2d2dcc
, deze wordt niet gevalideerd aangezien de resource-origin altijd gezet wordt door de FHIR resource service op een create):Scope Uitleg system/Patient.c(ruds)?resource-origin=3a2c98b5-298e-4f95-ab21-077d6b2d2dcc Specifieke create permissie op de Patient
resource voorDevice/3a2c98b5-298e-4f95-ab21-077d6b2d2dcc
, optioneel mag deze ook de read, update en/of delete bevattensystem/*.c(rud)?resource-origin=3a2c98b5-298e-4f95-ab21-077d6b2d2dcc Mag alle resources aanmaken met de eigen resource-origin, de parameter wordt niet geëvalueerd in het geval van een create system/Patient.cruds?resource-origin=3a2c98b5-298e-4f95-ab21-077d6b2d2dcc Mag alle acties uitvoeren op
Patient
resources met resource-originDevice/3a2c98b5-298e-4f95-ab21-077d6b2d2dcc
- hoeft de
- Indien de <action> GEEN create is, gaat het altijd om bestaande resources. Deze hebben per definitie een
resource-origin
extensie die aangeeft wie de eigenaar van de resource is. Haal de Resource(s) op en verifieer deresource-origin
waarden.Zoek een permissie op in de
access_token.scope
bij de geauthoriseerde applicatie-instantie aan de hand van de logical id van deresource-origin
, de <action> en <resource_type>. Bijvoorbeeld: voor eenUPDATE
op eenActivityDefinition
metresource-origin
Device/3a2c98b5-298e-4f95-ab21-077d6b2d2dcc
kan gezocht worden middels een match op de volgende reguliere expressie:system\/(?:ActivityDefinition|\*)\.c?r?ud?s?(?:\?[a-z0-9-=&]*resource-origin=3a2c98b5-298e-4f95-ab21-077d6b2d2dcc|(?=\s|$))
Deze regex dwingt af dat er eenu
voorkomt bij de action. Daarnaast moet OF de resource-origin voorkomen, of GEEN parameter gezet zijn. Dit laatste impliceert een ALL op permissie scope.De action karakters zijn volgorderlijk
c
, r, u,d en s
.system/ActivityDefinition.crdus
is dus NIET valide. - Indien niet aanwezig: FHIR resource service respond met een
403 Forbidden
.
Search Narrowing
Wanneer alle resources opgehaald worden voor een specifiek type, bijv. GET /Patient
, mogen enkel de resources teruggegeven worden waar de applicatie-instantie leesrechten op heeft. Dit wordt door de FHIR resource service opgelost middels een interceptor pattern
. De oplossing dient de huidige query-parameters te filteren en uit te breiden in het geval dat de permissie scope niet ALL
is.
De volgende flow wordt gehanteerd:
Subscription Narrowing
Het toevoegen van search narrowing kan als gevolg hebben dat de FHIR resource service een Subscription
afvuurt terwijl een applicatie-instantie daar geen toegang toe heeft. Bij het aanmaken van Subscriptions
dient dezelfde logica toegepast te worden als bij search narrowing, alleen dan op de Subscription.criteria
.