Data flows

NB: This is a draft specification!

The SSO mechanism involves four different system roles:

  • Browser: the internet browser that presents the user interface to the end user
  • App server: the web server of the third party application
  • FHIR server: the server that exposes an API to the ZorgDomein application
  • Auth server: the server that manages authorization of users. This server is maintained by ZorgDomein, 

During the process of SSO these systems exchange data according to the flow displayed in the diagram below.

ZD FHIR server
ZD Auth server
1. Launch app

Browser navigates to launch URL of external application. More details  

2. Requests authorization URLs

App requests authorization URLs from ZorgDomein. More details 

3. Provide authorization URLs

The ZorgDomein FHIR server responds with the requested URLs. More details  

4. Redirect to ZorgDomein authorization URL

App redirects browser to ZorgDomein authorization URL to request authorization code. More details  

5. Request authorization code

Browser requests ZorgDomein authorization page. More details  

6. Serve authorization page

ZorgDomein Auth server responds with authorization page. More details  

7. Send user approval

User authorizes request, browser sends approval to ZorgDomein Auth server. More details  

8. Provide authorization code, redirect to app

ZorgDomein authorization server responds with authorization code and redirects to app server. More details  

9. Provide authorization code

Browser sends authorization code to app server. More details  

10. Request access token

App server requests access token at ZorgDomein authorization server. More details  

11. Provide access token

ZorgDomein authorization server responds with access token. More details  

12. Request user details

App requests user details from ZorgDomein authorization server. More details  

13. Provide user details in FHIR resource

ZorgDomein replies with FHIR resource representing the user. More details  

14. SSO complete, serve app start page

SSO completed, app sends start page to browser. More details  

The flow starts with an autheniticated user in ZorgDomein. As displayed in the diagram the flow consists of the following steps:

1. Launch app

The user wants to navigate to an external application. To facilitate this the ZorgDomein frontend exposes a lauch URL that points to the external application. The user navigates to this URL in the browser, so the browser issues a HTTP GET request to the launch URL of the application server. The launch URL will contain the following query parameters:

  • launch – opaque identifier for this specific launch. This parameter must be communicated back to ZorgDomein at authorization time by passing along a launch parameter (see step 4/5).
  • iss – fixed value:  (base FHIR endpoint of ZorgDomein).

Example launch URL:

2. Requests authorization URLs

On receiving the launch notification, the app sends an HTTP GET request to the ZorgDomein FHIR server to query ZorgDomein’s Well-Known Uniform Resource Identifiers JSON document ( This resource contains (among other details) the OAuth authorization and token endpoints of ZorgDomein. The app needs these endpoints to request authorization at ZorgDomein in step 4.

3. Provide authorization URLs

The ZorgDomein FHIR server will respond with a Well-Known URI’s JSON document. The endpoint values can be extracted from the response (see example below). 

    "authorization_endpoint": "",
    "token_endpoint": "",
    "token_endpoint_auth_methods_supported": [
    "scopes_supported": [
    "capabilities": [

4. Redirect to ZorgDomein authorization URL

To send a request for an authorization code to the ZorgDomein authorization server, the app sends a HTTP redirect response to the browser, redirecting to the authorization URL with the following query parameters:

  • response_type – Fixed value: code (the OAuth authorization code flow is used, see Open ID specifications for details)
  • client_id – The client’s identifier. This identifier will be exchanged between ZorgDomein and app supplier during the registration process (see Registration of SMART apps).
  • redirect_uri – Must match one of the redirect URLs that have been registered at ZorgDomein during the registration process.
  • launch – Must contain the value of the launch id issued by ZorgDomein in step 1.
  • scope – Describes the access that the app needs. Multiple scopes can be defined separated by a space. Supported values:
    • openid – request an OpenID token .
    • profile – request access to the user's default profile claims. The following claims are supported and may be included in the ID token: name, family_name, given_name,  gender and birthdate
    • email – request access to the email and email_verified claims.
    • address – requests access to the address claim (see Open ID specifications for details).
    • phone – request access to the phone_number and phone_number_verified claims.
    • launch/patient –  request current patient context in ZorgDomein at launch time (id of FHIR Patient resource).
    • patient/  request access to read the Patient resource for the current patient.
    • patient/Appointment.write  request access to create new appointments for the current patient.
    • online_access  request a refresh token that can be used to obtain a new access token to replace an expired one, and that will be usable for as long as the end-user remains online. NB: ZorgDomein does not support the offline_access scope.
    • –  request the ZD number of the current transaction in ZorgDomein at launch time. 
  • state – An opaque value used by the app to maintain state between the request and callback. The ZorgDomein authorization server includes this value when redirecting the browser back to the app (see step 8). The parameter SHALL be used for preventing cross-site request forgery or session fixation attacks.
  • nonce (optional)  String value used to associate a client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the authentication request to the ID Token. For implementation notes, see section 15.5.2 of the OpenID specifications.
  • aud – Base URL of the ZorgDomein FHIR server: This parameter prevents leaking a genuine bearer token to a counterfeit resource server. Note: this aud value is the same as the launch's iss value.

Example redirect URL:

5. Request authorization page

Following the HTTP redirect that the browser receives from the app, the browser sends a HTTP GET request to the ZorgDomein authorization page. Through this page the app can request an authorization code. 

6. Serve authorization page

ZorgDomein responds with the authorization page which presents the authorization request to the user.

7. Send user approval

The user reviews and approves the authorization. The browser sends the authorization approval to the ZorgDomein authorization server.

8. Provide authorization code to browser

When approval has been received, the ZorgDomein authorization server generates an authorizaton code and communicates this code to the app server through an HTTP redirect to the app server. This causes the browser to redirect to the redirect_uri (as provided in step 4) with the following query parameters:

  • code  The authorization code generated by the authorization server.
  • state  The exact value received from the app server in step 4.

Example redirect URL:

9. Provide authorization code to app

Following the redirect command received from the ZorgDomein authorization server, the browser sends a HTTP GET request to the redirect_uri (i.e. the app) containing the authorization code and state parameters.

10. Request access token

After obtaining the authorization code, the app trades the code for an access token via HTTP POST to the ZorgDomein authorization server’s token endpoint URL, using content-type application/x-www-form-urlencoded. The following form parameters must be included in the POST:

  • grant_type – Fixed value: authorization_code.
  • code – Code that the app received from the ZorgDomein authorization server.
  • redirect_uri – The same redirect_uri used in the initial authorization request (step 4).

Example POST request:

POST /api/oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded


11. Provide access token

ZorgDomein authorization server responds with a JSON object that contains the following parameters:

  • access_token – The access token issued by the ZorgDomein authorization server.
  • token_type – Fixed value: Bearer.
  • expires_in – Lifetime in seconds of the access token, after which the token will not be accepted by the ZorgDomein FHIR server.
  • scope – Scope of access authorized. Note that this can be different from the scopes requested by the app.
  • id_token – Authenticated user identity and details. See ID token documentation for details.
  • refresh_token – Token that can be used to obtain a new access token, using the same or a subset of the original authorization grants.
  • patient - ID of the FHIR Patient resource representing the active patient content in ZorgDomein. 
  • – ZD number of the active transaction in ZorgDomein at launch time.
  • – URL the app should use when sending the user back to ZorgDomein when closing the app.

Example access token response:

  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJjbGllbnRfaWQiOiJteXNtYXJ0YXBwaWQiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIHBob25lIGxhdW5jaC9wYXRpZW50IGxhdW5jaC96ZG51bWJlciBwYXRpZW50L0FwcG9pbnRtZW50LndyaXRlIG9ubGluZV9hY2Nlc3MiLCJ1c2VyIjoiMWFmMjE2ZTQtNjFjYy00ZmE0LWJhOTMtYzE3MDhhZTVmNmUwIiwicGF0aWVudCI6IjliZTA3NDA4LWUyMDYtNGQ1Zi05YmRjLTcwMjRjMTg3NzY5YiIsInpkbnVtYmVyIjoiWkQxMjM0NTY3OCIsImlhdCI6MTU3MTMyNTg2MywiZXhwIjoxNTcxMzI3NjYzfQ.mdESytoX3Bl-3F1ag86_xe0YVigyaEV7BsvzVhYo9y4",
  "token_type": "Bearer",
  "expires_in": 1800,
  "scope": "openid profile email phone launch/patient patient/Appointment.write online_access",
  "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Inpvcmdkb21laW4tMjAxOTEwMTcxMTMwMDUzMCJ9.eyJpc3MiOiJodHRwczovL3pvcmdkb21laW4ubmwiLCJzdWIiOiIxYWYyMTZlNC02MWNjLTRmYTQtYmE5My1jMTcwOGFlNWY2ZTAiLCJhdWQiOiJteXNtYXJ0YXBwaWQiLCJleHAiOjE1NzEzMjc2NjMsImlhdCI6MTU3MTMyNTg2MywibmFtZSI6IkluZ3JpZCBUZXN0Z2VicnVpa2VyIC0gdmFuIFpvcmdEb21laW4iLCJmYW1pbHlfbmFtZSI6IlRlc3RnZWJydWlrZXIgLSB2YW4gWm9yZ0RvbWVpbiIsImdpdmVuX25hbWUiOiJJbmdyaWQiLCJnZW5kZXIiOiJmZW1hbGUiLCJiaXJ0aGRhdGUiOiIxOTc2LTEwLTE0IiwiZW1haWwiOiJpbmdyaWRAbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYWRkcmVzcyI6eyJmb3JtYXR0ZWQiOiJTdHJhYXR3ZWcgNjhcclxuMzYyMSBCUlxyXG5CcmV1a2VsZW4iLCJzdHJlZXRfYWRkcmVzcyI6IlN0cmFhdHdlZyA2OCIsImxvY2FsaXR5IjoiQnJldWtlbGVuIiwicG9zdGFsX2NvZGUiOiIzNjIxIEJSIn0sInBob25lX251bWJlciI6IjA2MTIzNDU2NzgiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOnRydWV9.KwfKMjvN3VXZr-Cs1gpgfZv6SrVGLp7F0uGdOIUm8Eg",
  "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJjbGllbnRfaWQiOiJteXNtYXJ0YXBwaWQiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIHBob25lIGxhdW5jaC9wYXRpZW50IGxhdW5jaC96ZG51bWJlciBwYXRpZW50L0FwcG9pbnRtZW50LndyaXRlIG9ubGluZV9hY2Nlc3MiLCJ1c2VyIjoiMWFmMjE2ZTQtNjFjYy00ZmE0LWJhOTMtYzE3MDhhZTVmNmUwIiwicGF0aWVudCI6IjliZTA3NDA4LWUyMDYtNGQ1Zi05YmRjLTcwMjRjMTg3NzY5YiIsInpkbnVtYmVyIjoiWkQxMjM0NTY3OCIsImlhdCI6MTU3MTMyNTg2M30.vc5rOoaRWS3wqzTG_UcEG1LGl1MKVHCmpMtAmumnYbA",
  "patient": "9be07408-e206-4d5f-9bdc-7024c187769b",
  "": "ZD12345678",
  "": ""

12. Request user details

Now that the app has obtained an access token, it is able to send authorized requests to the ZorgDomein FHIR server. To request user details, the app queries the FHIR resource that is specified in the fhirUser claim in the OpenID token. The HTTP request that the app server issues must include an Authorization header that presents the access token as a Bearer token:

Authorization: Bearer {{access_token}}

NB: {{access_token}} should be replaced with the actual value of the access token. 

13. Provide user details in FHIR resource

After validation of the access token in the request of the app, the ZorgDomein FHIR server will respond to the app with the requested FHIR resource.

14. SSO complete, serve app start page

After all user details have been obtained, a user session can be initiated in the app which completes the app launch. The app start page is sent to the browser.