CH UMZH Connect IG (R4)
1.0.0-cibuild - ci-build
CH UMZH Connect IG (R4), published by UMZH. This guide is not an authorized publication; it is the continuous build for version 1.0.0-cibuild built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/umzhconnect/umzhconnect-ig/ and changes regularly. See the Directory of published versions
private_key_jwt (asymmetric proof, no central PKI required)In this article:
In this article we address security, authorization, and trust frameworks suitable for an open yet controlled healthcare API ecosystem. Out of the perspective of our pilot-project with two participants exposing data to each other through open but secured APIs, we show a hands on guide how each participant can/must secure his APIs based on industry standards, and examine how these approaches are expandable as ecosystems grows in terms of participants, software vendors, and regulatory expectations.
The use case considered is one where the placer creates a task at the fulfiller referencing a service request on placer’s side, the fulfiller based on the task proceeds to fetch the corresponding service request, and proceeds with an API based to query and fetch further resources referenced.
OAuth 2.0 and OpenID Connect–based architectures are the de-facto standard today for securing APIs, Security profiles such as SMART on FHIR define standards for health-specific use-cases and the OpenID Foundation’s FAPI 2.0 sharpens security awareness by enforcing measures to mitigate particular risk scenarios. In this article we explore to what extent theses standards are applicable for our problem and where additional measures may be suitable.
Special attention is given to machine-to-machine interactions, which are central to referral and order workflows, and to design decisions around client authentication, including private key–based mechanisms, mutual TLS (mTLS), and layered combinations of both. The concept however should be extensible to user/human centric authentication and authorization and particularly compatible with the future E-ID initiative, identifying Swiss registered users.
Todays de-facto standard for securing Web-APIs is OAuth & OpenIDConnect. In general OAuth is quite loosely defined and allows various ways of implementation. On a very high-level you could think of it like the following:
An application (possibly in combination with a logged in user) would like to access data from an external service. It therefore requests a security token from an authorization authority by providing credentials and uses this token in the request to the data service to provide proof of access rights and hence being allowed to access the data.
We follow industry standards with the use of OAuth/OIDC to segregate duties between identity management, token issuance, authentication & authorization enforcement.
OAuth glossary
Authorization Server (AS) - The system that issues tokens after validating identity, credentials, or policies. Resource Server (RS) - The API or service that receives and validates tokens before granting access. Client - The application requesting access on behalf of a user or system. Access Token - A short‑lived credential the client uses to call APIs. Scopes - Fine‑grained permissions describing what the client is allowed to access. Claims - Attributes embedded in a token (e.g., user ID, roles, tenant, expiry). Client Authentication - How a client proves its identity to the authorization server (e.g., client secret, mTLS, private key JWT). Grant Type - The method a client uses to obtain tokens (e.g., Authorization Code, Client Credentials). Policy engine - system that evaluates rules (“policies”) to decide whether a specific action is allowed
flowchart LR
Client <-->|Client Authentication & Token Issue| AS[Authorization Server]
Client <-->|Presents Token<br>Grants or Denies Access| RS[Resource Server]
RS -->|Validates Token| AS
Machine-To-Machine communication
Our principal focus will be on machine-to-machine communication: an organization allowing access to a set of data records to another organization without knowing which person is actually sending the request. It is likely that in later scenarios this option should also be considered an can be achieved by using alternative OAuth flows.
The client-credentials OAuth flow is the common way to approach this, where the client presents credentials and information about the action is it about to execute (scopes) to the resource server and in exchange receives an access token.
The access token again the client injects in the request to the resource server (the organization holding the sensitive patient data) and the latter can validate the token and grant or deny access.
SMART on FHIR defines a standard way for apps to securely connect to healthcare data by combining:
In practice, it gives app developers a predictable, interoperable method to authenticate, obtain tokens, and read/write clinical data across different EHR systems without custom integrations.
In our particular case we use SMART in the context of our use cases, for example:
Our use-cases of referrals and external service requests strongly suggest to dynamically authorize the audience (the counter party) to a very limited data set. Think of creating a consent when the service request is created:
For a given time I authorize partyB (represented by clientX) to read all data referenced by my given service request.
This consent stands in contrast to commonly used ‘general consent’ by a patient for data usage in research. In our case the consent defines either a rule based or explicit set of resources which the counter party is authorized to access.
A consent with appropriate properties is typically stored at the consent issuers location, treated as a resource itself and receiving a unique identification at time of creation. This identification is commonly communicated to the counter party in combination with the given case an optionally made available to the authorization service as well.
The API consuming party (counter party) uses the consent identification in the authorization flow and ultimately the API provider extracts the consent, matches it to the request and grants access after verifying consistency of the consents rules with the current API request.
Consent as part of the authorization flow may logically not be necessary - the restricting party may query all its consents and check if one is matching the current API request. However defining the consent identification as part of the authorization flow and access token may significantly simplify the authorization enforcement. The API consumer in essence tells the API provider in which context the API request is executed.
The FHIR specification supports a dedicated consent resource. Any FHIR server implementation therefore enables the local storage of consents with associated logic.
Below is an example of the sequence of a request for a referenced resource and the authorization verification, permit and return, or deny workflow.
sequenceDiagram
title Referral and External Service Requests Resource Fetching Flow
participant C as Client (Fulfiller)
participant AS as Authorization Server
participant AG as API Gateway (Placer)
participant PE as Policy Engine
participant FHIR as FHIR Server / Consent Store (Placer)
Note over C,AS: Machine-to-machine: Client Credentials flow
C->>AS: Token request (client auth) + requested scopes<br/>(+ consent_id context if used)
AS-->>C: Access token (scopes + claims)<br/>(optional: includes consent_id claim, <br/>optional: sender-constrained)
C->>AG: API request + Authorization: Bearer <token>
AG->>AG: Validate token (sig, iss, aud, exp, scopes)<br/>(+ validate sender-constraint if FAPI)
AG->>PE: AuthZ decision request:<br/>(client identity, requested <br/>operation/resource,<br/>consent context from token/headers)
PE->>FHIR: Fetch/validate Consent (by consent_id)<br/>+ evaluate rules / ownership / audience
PE->>FHIR: Evaluate whether requested resource(s)<br/>are in ServiceRequest graph referenced by consent
PE-->>AG: Permit / Deny
alt Permit
AG->>FHIR: Forward request
FHIR->>C: Response: return permitted resources<br/>(+ optional fine-grained enforcement)
else Deny
AG-->>C: 403 Forbidden
end
An enterprise grade web-service architecture, involves a number of steps for processing an HTTP request - DMZ / Firewall, TLS (HTTPS) termination, authentication, request routing, request processing and fine-grained authorization on resource server, etc.
flowchart TB
Client -->|HTTP Request| API
API -->|grant?| PE[Policy engine]
PE -->|Yes/No| API
API[API gateway] --->|Route request| RS[Resource Server]
We can think of a 3 step process to enforce security:
A common approach would be to handle the first (and optinally the second) step in the API gateway and the second and third step by the policy engine. In our case it would mean to ensure that all requested resources are part of the 'child graph' of the service request, which is scope of the consent.
In general it should be mentioned that fine-grained authorization may be a very complex task to perform on the standard FHIR API due to a variaty of factors, such es a broad range of search parameters covered by standard FHIR APIs. This is quite well covered in this project: Google FHIR Info Gateway Our generapproach is to whitelist only the neccessary endpoints and parameters required to enable our use case. The complexity of the authorization enforcement is therefore essentially reduced.
As the basic client credentials flow is subject to a number of security weaknesses, we define a stepwise security up-leveling approach for client authentication. Initial integrations may start with basic client credentials to enable rapid onboarding and piloting. As participants move to production and access higher-risk scopes, authentication is upgraded to private_key_jwt, replacing shared secrets with asymmetric keys registered during onboarding—without requiring a central PKI. For the highest assurance scenarios, the ecosystem supports mutual TLS (mTLS), strengthening client identity binding and reducing token replay risks. This staged model preserves a consistent authorization flow while providing a clear, operationally manageable path to stronger security.
The authorization model and APIs remain stable, while the client authentication method is strengthened over time. This makes the ecosystem scalable: partners can join quickly with minimal operational overhead, and then adopt stronger mechanisms when justified by risk, regulatory requirements, or production needs.
client_id + shared secret used for token endpoint authentication.private_key_jwt (asymmetric proof, no central PKI required)| Level | Client authentication | When to use | Security benefits | Operational footprint |
|---|---|---|---|---|
| 1 | Basic client credentials (shared secret) | Sandbox, PoC, low-risk scopes, early pilots | Quick start; baseline access control | Secret distribution + rotation; higher blast radius if leaked |
| 2 | private_key_jwt (JWKS registered at onboarding) |
Production default; medium/high-risk scopes; external partners | No shared secrets; stronger client proof; easier key rotation | Manage JWKS + key rollover; validate signed assertions |
| 3 | mTLS (optionally sender-constrained tokens) | Highest-risk scopes; regulated workflows; large-scale ecosystem | Strong client identity binding; replay resistance | Certificate lifecycle + trust model; revocation/rotation processes |
Use policy triggers to make the ladder actionable and predictable. The goal is to avoid “security by negotiation” and keep onboarding consistent.
private_key_jwt)Mandate Level 2 when any of the following applies:
Mandate Level 3 when any of the following applies:
A possible scope mapping may look like:
The generic client credentials flow has potential security weaknesses. The main risks are:
Following the policies reaching level 3, high-risk, employing mTLS, which cryptographically binds the token (or at least the session) to the client’s TLS certificate, so the token is only usable when presented over a TLS connection that proves possession of the matching private key.
mTLS and other additional security enhancements are included in the definition of OpenID FAPI2.0 in order to mitigate these risks by adding standardized measurements defined by RFCs (RFC 5280, RFC 8705, RFC 6749, RFC 7519). In essence it defines how to
FAPI2.0 enforcement adds requirements to classical certification management with PKI-infrastructure. Reference implementations (like Denmark) make use of a central PKI-infrastructure and certificate issuance and signing which reduces client side complexity (trust store etc) however requires central trust and single point of failure risk.