Switching Context
Describes how client applications can switch context and request new tokens with updated context information from the Authentication Server (AS).
A key component of the eHealth Infrastructure security model is to switch context. Switching context means that the user asks the Authentication/Authorization Server (AS) to issue a new set of tokens where the content of the Access token contains a new context. The parameters for requesting a new context are any of the following:
Careteam
Patient
Episode of Care
Organization
To set a context, the requester needs to obtain what is available to be set in context.
Available Contexts
The available contexts for a given user can be obtained by querying the AS using an HTTP GET with the current Access token at the path /auth/realms/{realm name}/resource/ehealth-connect/contexts on the AS.
The result is an expanded tree that lists available careteams and organizations, e.g. for a clinical user:
Example Request
GET https://saml.exttest.ehealth.sundhed.dk/auth/realms/ehealth/resource/ehealth-connect/contexts
Response:
{
"care_teams": [
{
"id": "https://fut.com/fhir/CareTeam/4",
"name": "Careteam Nord"
"affiliation": {
"id": "https://fut.com/fhir/Organization/38",
"name": "Region Midtjylland, Aarhus Universitetshospital, Lungesygdomme"
},
"roles": [
"urn:dk:sundhed:ehealth:role:clinical_viewer"
]
},
{
"id": "https://fut.com/fhir/CareTeam/6",
"name": "Careteam Syd"
"affiliation": {
"id": "https://fut.com/fhir/Organization/1",
"name": "Aarhus Kommune, Center Syd"
},
"roles": [
"urn:dk:sundhed:ehealth:role:clinical_viewer",
"urn:dk:sundhed:ehealth:role:citizen_enroller"
]
}
],
"organizations": [
{
"id": "https://fut.com/fhir/Organization/1",
"name": "Aarhus Kommune, Center Syd",
"roles": [
"urn:dk:sundhed:ehealth:role:questionnaire_editor"
]
},
{
"id": "https://fut.com/fhir/Organization/2",
"name": "Æbeltoft Kommune, Afdeling Vest",
"roles": [
"urn:dk:sundhed:ehealth:role:terminology_administrator",
"urn:dk:sundhed:ehealth:role:questionnaire_editor"
]
}
]
}
Filtering contexts by program
As of release 2026.2, a contexts request can contain a program query parameter. This is a comma-delimited string of programs ( example: ?program=my-program-a,my-program-b) and is used to filter which contexts are returned by the server. The server will only return the contexts for the care teams that contain one of the programs from the program query string. If the query parameter is omitted, the server behaves as before 2026.1.
Mapping from Role to Privileges
As of Keycloak version 1.8.40, a list of the top-level roles for each available context is given in the “roles element“. Each top-level role is expanded to a set of privileges. This mapping can be obtained by querying (HTTP GET with the current Access token) the AS at the path /auth/realms/{realm name}/resource/ehealth-connect/groups. The result is a map of top-level roles to privileges. The example request and response shown below illustrate the concept and are not intended to be normative, complete or kept up-to-date.
Groups
GET https://saml.exttest.ehealth.sundhed.dk/auth/realms/ehealth/resource/ehealth-connect/groups
{
"urn:dk:sundhed:ehealth:role:questionnaire_editor": [
"Questionnaire.update",
"DocumentReference.write",
"DocumentReference.*",
"Questionnaire.patch",
"DocumentReference.read",
"DocumentReference.update",
"DocumentReference.search",
"Organization.read",
...
],
"urn:dk:sundhed:ehealth:role:clinical_viewer": [
"DeviceUseStatement.search",
"Condition.search",
"DeviceMetric.read",
"DocumentReference.read",
"DocumentReference.search",
"RestrictionCategory$none",
"$search-measurements",
...
],
"urn:dk:sundhed:ehealth:role:terminology_administrator": [
"CodeSystem.write",
"Terminology Administrator",
"ConceptMap.write",
"ValueSet.write",
"NamingSystem.write"
],
"urn:dk:sundhed:ehealth:role:citizen_enroller": [
"Condition.search",
"CarePlan$update-care-teams",
"DocumentReference.read",
"Consent.create",
"DocumentReference.search",
"CareTeam.read",
"Consent.update",
"ServiceRequest.delete",
"Consent.patch",
"EpisodeOfCare.write",
"Questionnaire.search",
...
],
...
}Setting the Context
To set the context, the AS can be requested with a valid refresh token using an HTTP POST (x-www-form-urlencoded) against auth/realms/{realm name}/protocol/openid-connect/token with the required and optional parameters listed below. The result is a valid Access Token Response[1] where the access token in the response will have the requested context set.
[1] https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/
Example request:
Example context
POST /auth/realms/ehealth/protocol/openid-connect/token
Accept-Encoding: text
Content-Type: application/x-www-form-urlencoded
Accept: */*
Cache-Control: no-cache
Host: login.fut.trifork.com
Content-Length: 941
Connection: keep-alive
grant_type=refresh_token&
client_id=keyservice_client&
refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyNWIwYzE0ZS05ZTRhLTQ2NTAtODAzMS0xMjM4YjBhNGRjMjMifQ.eyJqdGkiOiJiOWRmMDAyYi1jN2VlLTRmZmEtYWU1MS00OGVlMGZjMDMyNWUiLCJleHAiOjE1NjYzODUwNDMsIm5iZiI6MCwiaWF0IjoxNTY2MzgzMjQzLCJpc3MiOiJodHRwczovL2xvZ2luLmZ1dC50cmlmb3JrLmNvbS9hdXRoL3JlYWxtcy9laGVhbHRoIiwiYXVkIjoiaHR0cHM6Ly9sb2dpbi5mdXQudHJpZm9yay5jb20vYXV0aC9yZWFsbXMvZWhlYWx0aCIsInN1YiI6ImFmYWZlYTJhLTY1ZWQtNDJhNy04YjMzLWMxNTdkYTIyYTA5NyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJrZXlzZXJ2aWNlX2NsaWVudCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjFlYjIxNjhjLTVlN2EtNGRiMi04ZTVlLWI3NzVjNGRkNWMxOSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIn0.Yv22YYcyQYYnj_OJMJ3kwsgq9gpAnHhtTFUfcbXLRcs&
organization_id=https%3A%2F%2Ffut.com%2Ffhir%2FOrganization%2F38&
care_team_id=https%3A%2F%2Ffut.com%2Ffhir%2FCareTeam%2F4&
episode_of_care_id=https%3A%2F%2Ffut.com%2Ffhir%2FEpisodeOfCare%2F10&
patient_id=https%3A%2F%2Ffut.com%2Ffhir%2FPatient%2F8
Note: The original JWT used to obtain a new JWT with the context set is still valid for other operations.
Parameter name | Description |
|---|---|
client_id | Required. The OAuth2 client id |
grant_type | Required. Fixed to the value of the ‘refresh_token’ |
refresh_token | Required. The refresh token of the current session |
care_team_id (context) | Optional. A valid absolute FHIR URI pointing to a Careteam resource. This adds implicit organization context given the organization constraint in the OIO BPP structure |
organization_id (context) | Optional. A valid absolute FHIR URI pointing to an Organization resource |
episode_of_care_id (context) | Optional. This adds implicit patient context. A valid absolute FHIR URI pointing to an Episode of Care resource |
patient_id (context) | Optional. A valid absolute FHIR URI pointing to a Patient resource |
Example: Access token with context
Context example
{
"jti": "2ef5b6b1-a667-40f5-b468-f475cdcef5ec",
"exp": 1556110351,
"nbf": 0,
"iat": 1556110051,
"iss": "https://inttest.ehealth.sundhed.dk/auth/realms/inttest",
"aud": "EHealth",
"sub": "88c4feb3-f87a-43c6-9141-fc03a3944ad6",
"typ": "Bearer",
"name": "Lasse Læge-Dam",
"azp": "EmployeeClient",
"auth_time": 0,
"session_state": "e03ccef7-b0b1-4f68-8e16-6fc2f865a967",
"acr": "1",
"user_id": "e03ccef7-b0b1-4f68-8e16-6fc2f865a922",
"user_type": "SYSTEM",
"realm_access": {
"roles": [
"offline_access",
"uma_authorization",
"Patient.read",
"Patient.write"
]
},
"context": {
"organization_id": "https://fut.com/fhir/Organization/38",
"care_team_id": "https://fut.com/fhir/CareTeam/4",
"episode_of_care_id": "https://fut.com/fhir/EpisodeOfCare/10",
"patient_id": "https://fut.com/fhir/Patient/8"
},
"scope": "profile openid ehealth",
"preferred_username": "C=DK,O=TRIFORK A/S // CVR:20921897,CN=Lasse Læge-Dam,Serial=CVR:20921897-RID:93134986"
}
Sequence Flow
The diagram below illustrates the interacting parts when logging in and requesting a context: