Authentifizierung klärt: Wer bist du? Autorisierung klärt: Was darfst du tun?
Bei der NovaHealth reicht es beispielsweise nicht aus, festzustellen, dass eine Anfrage von der Ärztin Dr. Sarah Weber stammt. Die Patienten-API muss zusätzlich entscheiden: Darf Sarah Patientendaten lesen? Darf sie Befunde verändern? Und darf sie auf die Daten dieses konkreten Patienten zugreifen?

„Wir haben die Authentifizierung jetzt ziemlich gründlich abgesichert. Wenn die API weiß, wer sie aufruft, weiß sie dann nicht automatisch auch, was diese Person darf?“
„Nein. Ein gültiges Access Token kann bestätigen, in welchem Sicherheitskontext die Anfrage erfolgt. Ob Sarah damit Patientendaten lesen darf – und vor allem welche – muss die API zusätzlich prüfen. Genau darum geht es bei der Autorisierung.“

Die Grundlagen von RBAC (Role-Based Access Control) und ABAC (Attribute-Based Access Control) kennst du bereits aus Modul B4. Zur Erinnerung: Bei RBAC werden Berechtigungen Rollen wie Arzt, Labor oder Admin zugeordnet. ABAC kann zusätzlich Eigenschaften des Benutzers, der Ressource oder des Kontexts berücksichtigen – beispielsweise, ob Sarah die behandelnde Ärztin des Patienten ist.
Bei APIs kommen weitere Mechanismen hinzu. Besonders wichtig sind Scopes und die objektbezogene Autorisierung.
In OAuth 2.0 beschreiben Scopes den Umfang des Zugriffs, den ein Client anfordert. Beispielsweise könnte die Webanwendung der NovaHealth folgende Scopes anfordern:
scope=read:patienten write:termine
read:patienten steht hier für das Lesen von Patientendaten, write:termine für das Verändern von Terminen. Die konkreten Bezeichnungen werden vom Authorization Server bzw. dem jeweiligen API-System festgelegt.
📌 Der Client fordert Scopes an. Der Authorization Server entscheidet, welche Scopes tatsächlich gewährt werden.
Die gewährten Scopes sind anschließend mit dem Access Token verknüpft. Bei einem JWT könnten sie beispielsweise als Claim enthalten sein:
{
"sub": "sarah.weber",
"aud": "patienten-api",
"scope": "read:patienten write:termine"
}
Die Patienten-API kann damit prüfen, ob das Token grundsätzlich zum Lesen von Patientendaten berechtigt ist. Scopes unterstützen damit das Least-Privilege-Prinzip: Ein Client sollte nur die Berechtigungen erhalten, die er tatsächlich benötigt. Aber:
⚠️ Der passende Scope allein bedeutet noch nicht, dass der konkrete Zugriff erlaubt ist.
read:patienten bedeutet nicht automatisch, dass Sarah jeden Patienten lesen darf.
Scopes allein reichen für die Autorisierung noch nicht aus. Die API muss zusätzlich prüfen, ob der Benutzer die angeforderte Funktion überhaupt ausführen darf. Eine Ärztin darf beispielsweise Patientendaten lesen und Befunde ergänzen. Das bedeutet aber nicht automatisch, dass sie administrative Funktionen wie
DELETE /api/patienten/12345
oder
GET /api/admin/benutzer
aufrufen darf.
Fehlt eine solche Prüfung, spricht OWASP von Broken Function Level Authorization (BFLA). Ein Angreifer versucht dabei beispielsweise, administrative Endpunkte direkt aufzurufen oder die HTTP-Methode von GET auf PUT oder DELETE zu ändern. Die API muss deshalb bei jedem Endpunkt und jeder Aktion serverseitig prüfen, ob der Benutzer diese Funktion ausführen darf.
📌 Best Practice: Autorisierungsprüfungen sollten nach dem Prinzip Deny by Default arbeiten: Eine Funktion ist zunächst nicht erlaubt und wird nur freigegeben, wenn die erforderliche Berechtigung ausdrücklich festgestellt wurde.
Nehmen wir an, Sarah ruft folgende Ressource auf:
GET /api/patienten/12345
Authorization: Bearer <Access-Token>
Die API könnte bereits festgestellt haben:
Jetzt fehlt aber noch eine entscheidende Frage: Darf Sarah auf Patient 12345 zugreifen?
Vielleicht behandelt sie diesen Patienten. Patient 67890 gehört dagegen zum Behandlungsbereich eines anderen Arztes. Damit lässt sich die Autorisierung vereinfacht so zusammenfassen:

Fehlt die letzte Prüfung, kann eine Broken Object Level Authorization (BOLA) entstehen. BOLA steht in den OWASP API Security Top 10 2023 als API1:2023 an erster Stelle. Angenommen, Sarah darf auf diesen Patienten zugreifen:
GET /api/patienten/12345
Ein Angreifer bzw. ein Benutzer mit gültigem Account verändert nun lediglich die ID:
GET /api/patienten/12346
Liefert die API auch Patient 12346 zurück, ohne zu prüfen, ob der angemeldete Benutzer auf dieses konkrete Objekt zugreifen darf, liegt eine BOLA-Schwachstelle vor.
Ein stark vereinfachtes Beispiel:
# Unsicher
def get_patient(patient_id):
return db.find(patient_id)
Hier wird der Patient lediglich anhand seiner ID aus der Datenbank geladen – ohne zu prüfen, ob der angemeldete Benutzer auf ihn zugreifen darf.
# Besser
def get_patient(patient_id, user):
patient = db.find(patient_id)
if not can_read_patient(user, patient):
return 403
return patient
Die Berechtigungsprüfung muss serverseitig erfolgen. Einen Button in der Benutzeroberfläche auszublenden, schützt die API nicht – ein Angreifer kann sie direkt aufrufen.
Auch einzelne Eigenschaften können geschützt sein: Selbst wenn ein Benutzer auf ein Objekt zugreifen darf, bedeutet das nicht automatisch, dass er alle Eigenschaften lesen oder verändern darf. Eine API sollte deshalb gegebenenfalls auch auf Feldebene prüfen, welche Daten zurückgegeben oder geändert werden dürfen. Fehlt diese Prüfung, spricht OWASP von Broken Object Property Level Authorization (BOPLA).
UUIDs wie
/patienten/550e8400-e29b-41d4-a716-446655440000
erschweren das systematische Erraten von IDs gegenüber:
/patienten/43
Sie ersetzen aber keine Autorisierungsprüfung. Kennt ein Angreifer eine gültige UUID, muss die API den unberechtigten Zugriff trotzdem verhindern.
Ein reales Beispiel dafür ist eine Schwachstelle in der FCC-DIRS-API: Ein authentifizierter Benutzer mit niedrigen Rechten konnte eine numerische userid im API-Pfad verändern und dadurch Profile und zugehörige Daten anderer Benutzer abrufen. Die technische Beschreibung der Schwachstelle findest du im Bugcrowd-Bericht.
⚠️ Merke: Authentifizierung allein reicht nicht. Eine API muss bei jedem geschützten Zugriff prüfen: Darf dieses Token diese Aktion ausführen? Darf dieser Benutzer diese Funktion verwenden? Darf er auf genau dieses Objekt zugreifen? Und darf er die angeforderten Eigenschaften dieses Objekts lesen oder verändern?
Schauen wir, ob du die Autorisierungskonzepte bei APIs verinnerlicht hast.