---
{
  "title": "FHIR RBAC mit Keycloak & SMART on FHIR v2",
  "description": "Rollenbasierte Zugriffskontrolle für FHIR-Ressourcen mit Keycloak und SMART on FHIR v2: Scopes, Rollen-Mapping, Token-Konfiguration und Aidbox-Durchsetzung.",
  "date": "2025-10-14",
  "author": "Aleksandr Kislitsyn",
  "reading-time": "7 minutes",
  "tags": [
    "Integrations",
    "System Design"
  ]
}
---
Der Aufbau von Healthcare-Anwendungen auf Basis eines FHIR-Servers ist gängige Praxis geworden. FHIR-Server bieten standardisierte Speicherung und APIs für klinische Ressourcen und ermöglichen es Entwicklern, sich auf die Implementierung von Funktionen zu konzentrieren, anstatt die Infrastruktur für Gesundheitsdaten zu verwalten. Dies wirft jedoch eine wichtige Frage auf: Wie stellen Sie sicher, dass verschiedene Benutzer nur die Daten sehen, auf die sie berechtigt sind?

Ein Arzt sollte beispielsweise vollständigen Zugriff auf Patientenbeobachtungen haben – sowohl auf Laborbefunde als auch auf Vitalzeichen. Ein Labortechniker hingegen sollte nur abgeschlossene Laborbefunde sehen, die für seine Arbeit relevant sind. Die Implementierung dieser Art von feingranularer Zugriffskontrolle erfordert traditionell komplexe Logik auf Anwendungsebene, benutzerdefinierte Autorisierungsregeln und umfangreiche Tests.

Es gibt einen besseren Weg: einen standardbasierten Ansatz, der Ihren vorhandenen Identity Provider nutzt und keinerlei benutzerdefinierten Autorisierungscode in Ihrer Anwendung erfordert.

In diesem Beitrag erläutern wir, wie Sie eine ausgefeilte rollenbasierte Zugriffskontrolle (RBAC) für FHIR-Ressourcen mithilfe von [Keycloak](https://www.keycloak.org/)-Rollen (einer Open-Source-Lösung für Identity- und Access-Management), die SMART on FHIR V2-Scopes zugeordnet werden, und der automatischen Durchsetzung durch Aidbox implementieren. Das Beste daran: Derselbe API-Endpunkt gibt je nach anfragender Person unterschiedliche Daten zurück – vollständig transparent.

## Das Problem: Ein Endpunkt, mehrere Zugriffsebenen
Stellen Sie sich vor, Sie entwickeln eine Healthcare-Anwendung auf Basis des FHIR-Servers mit zwei Benutzertypen:

**Dr. Sarah (Ärztin)**
- Muss alle Patientenbeobachtungen einsehen können
- Überprüft sowohl Laborbefunde als auch Vitalzeichen
- Trifft klinische Entscheidungen auf Grundlage vollständiger Patientendaten

**Mike (Labortechniker)**
- Arbeitet ausschließlich mit abgeschlossenen Laborbefunden
- Sollte keine Vitalzeichen oder vorläufigen Labordaten sehen
- Benötigt Zugriff, der auf seine spezifische Aufgabe beschränkt ist

Beide Benutzer rufen denselben API-Endpunkt auf: GET /fhir/Observation. Aber sie sollten völlig unterschiedliche Ergebnisse sehen.

Traditionell würden Entwickler dieses Problem durch folgende Maßnahmen lösen:
- Benutzerdefinierte Middleware zur Überprüfung von Benutzerrollen
- Komplexe Abfragefilter im Anwendungscode
- Separate API-Endpunkte oder Parameter für verschiedene Benutzertypen
- Umfangreiche Unit-Tests für jedes Autorisierungsszenario
- Wartungsaufwand bei sich ändernden Anforderungen

Dieser Ansatz funktioniert, ist jedoch **schwer zu warten** und **fehleranfällig**, wenn sich Anforderungen weiterentwickeln. Es gibt einen besseren Weg.

## Die Lösung: SMART-Scopes treffen auf Keycloak-Rollen
SMART on FHIR V2 führt ein leistungsstarkes Konzept ein: [**Scopes mit Abfrageparametern**](https://build.fhir.org/ig/HL7/smart-app-launch/scopes-and-launch-context.html#finer-grained-resource-constraints-using-search-parameters). Anstatt nur breiten Zugriff zu gewähren wie „dieser Benutzer kann Observations lesen", können Sie exakte Regeln festlegen, zum Beispiel:


```javascript
user/Observation.rs?category=laboratory&status=final
```


Dieser Scope bedeutet: „Der Benutzer kann Observations lesen und durchsuchen, jedoch nur Laborbeobachtungen mit dem Status ‚final'."

Durch die Kombination mit dem Composite-Rollen-System von Keycloak können wir:
- **Granulare Berechtigungen** als einfache Keycloak-Rollen definieren (jede repräsentiert einen SMART-Scope)
- **Sie zu Aufgabenfunktionen zusammenfassen** mithilfe von Composite-Rollen (wie „physician" oder „lab_technician")
- **Composite-Rollen automatisch auflösen** in SMART-Scopes im Zugriffstoken
- **Aidbox die Regeln automatisch durchsetzen lassen** – kein benutzerdefinierter Code erforderlich

So funktioniert der Ablauf:


```javascript
User Login → Keycloak resolves roles → Token with SMART scopes →
Aidbox validates token → Automatic data filtering → Correct results
```


## Implementierung: Aufbau der Rollenstruktur
### Schritt 1: Basisrollen definieren (granulare SMART-Scopes)

In Keycloak erstellen wir Basisrollen, die direkt auf SMART on FHIR V2-Scopes abgebildet werden:

**Basisrollen:**
- `user/Patient.rs` – Patientendaten lesen und durchsuchen
- `user/Encounter.rs` – Begegnungen lesen und durchsuchen
- `user/Observation.rs` – ALLE Observations lesen und durchsuchen
- `user/Observation.rs?category=laboratory&status=final` – NUR abgeschlossene Laborbefunde lesen und durchsuchen

Diese Basisrollen sind die Bausteine. Jede repräsentiert eine spezifische Berechtigung mit optionalen Abfrageparameter-Einschränkungen.

### Schritt 2: Composite-Rollen erstellen (Aufgabenfunktionen)

Als Nächstes kombinieren Sie Basisrollen zu Composite-Rollen, die reale Aufgabenfunktionen widerspiegeln:

**Physician-Rolle** (vollständiger klinischer Zugriff):
- `user/Patient.rs`
- `user/Encounter.rs`
- `user/Observation.rs`

**Lab-Technician-Rolle** (beschränkt auf Laborbefunde):
- `user/Patient.rs`
- `user/Observation.rs?category=laboratory&status=final`

Beachten Sie, dass die Lab-Technician-Rolle den eingeschränkten Observation-Scope verwendet – dadurch wird der Zugriff auf Vitalzeichen oder Entwurfsergebnisse verhindert.

### Schritt 3: Den Token-Mapper konfigurieren

Hier geschieht die eigentliche Magie. Keycloak wandelt Rollen in [Zugriffstoken](/blog/token-introspection-in-fhir) um. Das Token ist eine kleine, sichere Datei (JSON Web Token – JWT), die jede API-Anfrage begleitet und Aidbox mitteilt, was der Benutzer tun darf. Wir müssen Keycloak dazu bringen:
- Composite-Rollen (z. B. „physician") in ihre grundlegenden Basisrollen aufzulösen
- Diese Basisrollen im `scope`-Claim des Tokens als SMART-Scopes einzuschließen
- Den Claim `atv: "2"` hinzuzufügen, um anzugeben, dass im Token SMART on FHIR-Scopes zur Verarbeitung vorhanden sind

Dies erreichen wir mithilfe eines benutzerdefinierten skriptbasierten Protocol Mappers. Wenn sich ein Labortechniker anmeldet, sieht sein Zugriffstoken folgendermaßen aus:


```json
{
  "sub": "lab_technician",
  "scope": "user/Patient.rs 
            user/Observation.rs?category=laboratory&status=final",
  "atv": "2"
}
```


### Schritt 4: Aidbox für die automatische Durchsetzung konfigurieren

Dies ist der eleganteste Teil: Aidbox setzt die im Token definierten Zugriffsregeln automatisch durch. Alles, was Sie benötigen, ist:
- **TokenIntrospector** – Überprüft, ob das Token gültig und von Ihrer Keycloak-Instanz ausgestellt wurde:


```javascript
{
  "resourceType": "TokenIntrospector",
  "jwt": {
    "iss": "http://localhost:8888/realms/master"
  },
  "type": "jwt",
  "jwks_uri": 
    "http://keycloak:8888/realms/master/protocol/openid-connect/certs",
  "id": "external-auth-server",
  "resourceType": "TokenIntrospector"
}
```


  - **AccessPolicy** – Erlaubt Anfragen mit validierten Token:


```javascript
{
  "resourceType": "AccessPolicy",
  "id": "keycloak-access-policy",
  "engine": "matcho",
        "matcho": {
          "jwt": {
            "iss": "http://localhost:8888/realms/master"
          }
        }
}
```


Das ist alles. Wenn Aidbox eine Anfrage mit einem Token empfängt, das atv: "2" und SMART-Scopes enthält, wird automatisch:
- Die Scopes analysiert, um erlaubte Ressourcentypen zu bestimmen
- Abfrageparameter-Filter aus den Scopes angewendet
- Nur Daten zurückgegeben, die den Scope-Einschränkungen entsprechen
- Anfragen für nicht autorisierte Ressourcentypen abgelehnt

Kein benutzerdefinierter Autorisierungscode. Keine komplexe Zugriffskontrolllogik. Es funktioniert einfach.

## Praxisbeispiel
Gehen wir beide Benutzerszenarien durch, um zu sehen, wie derselbe API-Aufruf unterschiedliche Ergebnisse liefert. Stellen Sie sich vor, Sie haben Ihr System mit Aidbox, verbunden mit Keycloak, eingerichtet, und sowohl Dr. Sarah (die Ärztin) als auch Mike (der Labortechniker) nutzen dieselbe Anwendung.

Im System gibt es zwei **Observation**-Ressourcen:
- **Hämoglobin** – eine Laborbeobachtung mit dem Status „final"
- **Blutdruck** – eine Vitalzeichen-Beobachtung

Beide Benutzer greifen auf denselben Endpunkt zu: `GET /fhir/Observation`
Aber Aidbox gibt je nach anfragender Person unterschiedliche Antworten zurück.

### Test 1: Ärztlicher Zugriff (Vollzugriff)
**Anmeldedaten:**


```javascript
Username: physician
Password: password
```


**API-Aufruf:**


```javascript
GET /fhir/Observation
Authorization: Bearer <physician_token>
```


**Token-Scopes:**


```javascript
user/Patient.rs user/Encounter.rs user/Observation.rs
```


**Ergebnis:** Die Ärztin sieht **beide Observations**:
- Hämoglobin (Labor, final)
- Blutdruck (Vitalzeichen)

Der Scope `user/Observation.rs` gewährt uneingeschränkten Zugriff auf alle Observation-Ressourcen.

### Test 2: Zugriff des Labortechnikers (eingeschränkter Zugriff)
**Anmeldedaten:**


```javascript
Username: lab_technician
Password: password
```


**API-Aufruf:**


```javascript
GET /fhir/Observation
Authorization: Bearer <lab_technician_token>
```


**Token-Scopes:**


```javascript
user/Patient.rs 
user/Observation.rs?category=laboratory&status=final
```


**Ergebnis:** Der Labortechniker sieht **nur eine Observation**:
- Hämoglobin (Labor, final)

Die Blutdruck-Observation wird herausgefiltert, da sie nicht den Scope-Anforderungen entspricht:
- Ihre Kategorie ist „vital-signs" (nicht „laboratory")
- Der Scope erfordert ausdrücklich `category=laboratory&status=final`

Gleicher Endpunkt, gleicher Code, unterschiedliche Ergebnisse je nach anfragender Person. Keine benutzerdefinierte Filterlogik erforderlich.

## Selbst ausprobieren
Möchten Sie dies in der Praxis sehen? Das vollständige [Beispiel](https://github.com/Aidbox/examples/tree/main/aidbox-features/smart-keycloak-roles) ist bereit, mit Docker ausgeführt zu werden.

**Voraussetzungen:** Docker und Docker Compose müssen installiert sein

**Schnellstart:**
- **Klonen Sie das [Repository](https://github.com/Aidbox/examples)** **und navigieren Sie zum Beispiel:**


```javascript
cd aidbox-features/smart-keycloak-roles
```


  - **Starten Sie alle Dienste:**


```javascript
docker compose up --build
```


  - **Aidbox initialisieren:** Navigieren Sie zu 
[http://localhost:8080](http://localhost:8080) 
und schließen Sie die Aidbox-Initialisierung ab.

  - **Demo-Anwendung öffnen:** Navigieren Sie zu 
[http://localhost:3000](http://localhost:3000).

  - **Beide Benutzerrollen testen:**

Melden Sie sich als `physician/password` an – sehen Sie alle Observations

- Klicken Sie auf „Start Over" und melden Sie sich als `lab_technician/password` an – sehen Sie nur Laborbefunde

Die Demo-Anwendung zeigt nebeneinander, auf was jeder Benutzer zugreifen kann, und macht die Unterschiede in der Zugriffskontrolle unmittelbar sichtbar.

## Wesentliche Erkenntnisse
Dieser Ansatz bietet mehrere bedeutende Vorteile:

**1. Kein benutzerdefinierter Autorisierungscode**
Ihre Anwendung muss Rollen weder verstehen noch Filterlogik implementieren. Aidbox erledigt dies automatisch auf Basis von SMART-Scopes.

**2. Zentrale Zugriffskontrolle**
Alle Rollendefinitionen befinden sich in Ihrem Identity Provider (Keycloak). Ändern Sie die Berechtigungen einer Rolle an einer Stelle, und die Änderung gilt überall.

**3. Standardbasiert**
Basiert auf SMART on FHIR V2, einem etablierten Standard für die Interoperabilität im Gesundheitswesen. Keine proprietären Lösungen oder Vendor-Lock-in.

**4. Feingranulare Kontrolle**
Abfrageparameter-Einschränkungen (?category=laboratory&status=final) ermöglichen präzise Zugriffskontrolle ohne komplexe benutzerdefinierte Regeln.

**5. Einfach erweiterbar**
Benötigen Sie eine neue Rolle? Erstellen Sie in Keycloak eine Composite-Rolle, die die entsprechenden Basisrollen kombiniert. Keine Codeänderungen erforderlich.

**Weitere Informationen:**
- [SMART on FHIR Scopes in Aidbox](https://www.health-samurai.io/docs/aidbox/access-control/authorization/smart-on-fhir/smart-scopes-for-limiting-access)
- [Keycloak Role-Based Access Control](https://www.keycloak.org/docs/latest/server_admin/#_composite-roles)
- [SMART App Launch Framework](https://hl7.org/fhir/smart-app-launch/)

## Fazit
Feingranulare Zugriffskontrolle für FHIR-Ressourcen muss nicht kompliziert sein. Durch die Kombination von SMART on FHIR V2-Scopes, dem Composite-Rollen-System von Keycloak und der automatischen Scope-Durchsetzung durch Aidbox können Sie eine ausgefeilte RBAC implementieren, ohne benutzerdefinierten Autorisierungscode zu schreiben.

Das Ergebnis: sicherere Anwendungen, einfachere Wartung und bessere Ausrichtung an Healthcare-Interoperabilitätsstandards.

Sind Sie bereit, rollenbasierte Zugriffskontrolle in Ihrer FHIR-Anwendung zu implementieren? Starten Sie mit dem Beispiel-Repository und passen Sie die Rollen an Ihren spezifischen Anwendungsfall an.