Authentifizierung und Autorisierung
Alle Aufrufe der REST-Schnittstelle sind
geschützt. Die Plattform validiert bei jeder Anfrage ein JSON Web Token (JWT),
das von Keycloak (dem Identity-Provider der Plattform) ausgestellt wird. Das
Token wird als Bearer-Token im Authorization-Header mitgeschickt:
Authorization: Bearer <access_token>
Keycloak stellt das Token über einen OAuth2-Flow aus. Für externe Anbindungen werden zwei Flows unterstützt:
- Client-Credentials-Flow – für System-zu-System-Anbindungen ohne Nutzerinteraktion (empfohlen für Integrationen).
- Authorization-Code-Flow – für Anwendungen, in denen sich ein menschlicher Nutzer interaktiv anmeldet.
Welche Zugangsdaten (Client, Secret, Realm-URL) Sie verwenden, erhalten Sie vom Betreiber der Plattform.
Voraussetzungen
Damit ein Token für die API akzeptiert wird, muss es zwei Bedingungen erfüllen:
- Der
roles-Claim enthält die RolleROLE_SERVICEUSER(für lesenden und schreibenden Zugriff auf die regulären Endpunkte). - Der
groups-Claim enthält genau einen Eintrag der FormTENANT_<name>, der Ihren Tenant bestimmt. Über diesen Eintrag wird die mandantengetrennte Datenhaltung aufgelöst.
Beide Claims werden beim Anlegen des Clients bzw. Nutzers durch den Plattform-Betreiber konfiguriert – Sie müssen dazu nichts weiter unternehmen.
Endpunkte
Keycloak stellt die relevanten Endpunkte unter der Realm-Basis-URL bereit. Die folgenden Platzhalter kommen in den Beispielen zum Einsatz:
| Platzhalter | Bedeutung | Beispiel |
|---|---|---|
<keycloak-host> | Host der Keycloak-Instanz (inkl. /auth-Pfad) | https://auth.example.com/auth |
<realm> | Name des Realms | hetida-platform-standalone |
<platform-host> | Host der Plattform-API | https://platform.example.com |
Daraus ergibt sich:
- Token-Endpunkt:
<keycloak-host>/realms/<realm>/protocol/openid-connect/token - Authorization-Endpunkt:
<keycloak-host>/realms/<realm>/protocol/openid-connect/auth - API-Basis-URL:
<platform-host>/api
Client-Credentials-Flow (empfohlen)
Beim Client-Credentials-Flow authentifiziert sich Ihre Anwendung mit einer Client-ID und einem Client-Secret – ohne Nutzerkontext. Sie erhalten ein Access-Token direkt vom Token-Endpunkt und verwenden es für die API-Aufrufe.
Beispiel in Python
Das folgende Beispiel holt ein Token und liest anschließend die Asset-Typen des
Tenants aus. Es verwendet die Bibliothek
requests (pip install requests).
import requests
KEYCLOAK_HOST = "https://<keycloak-host>" # inkl. /auth, falls konfiguriert
REALM = "<realm>"
PLATFORM_HOST = "https://<platform-host>"
CLIENT_ID = "<client-id>"
CLIENT_SECRET = "<client-secret>"
TOKEN_URL = f"{KEYCLOAK_HOST}/realms/{REALM}/protocol/openid-connect/token"
API_BASE = f"{PLATFORM_HOST}/api"
def fetch_access_token() -> str:
response = requests.post(
TOKEN_URL,
data={"grant_type": "client_credentials"},
auth=(CLIENT_ID, CLIENT_SECRET), # HTTP Basic Authentication
timeout=10,
)
response.raise_for_status()
return response.json()["access_token"]
def main() -> None:
token = fetch_access_token()
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(f"{API_BASE}/asset-types", headers=headers, timeout=10)
response.raise_for_status()
for asset_type in response.json():
print(asset_type)
if __name__ == "__main__":
main()
Access-Tokens sind nur kurz gültig (in der Regel wenige Minuten). Fordern Sie für lang laufende Prozesse rechtzeitig ein neues Token an, statt ein bestehendes zu zwischenspeichern.
Behandeln Sie das Client-Secret wie ein Passwort: Nicht in Quellcode-Repositories einchecken, sondern z. B. über Umgebungsvariablen oder einen Secret-Store bereitstellen.
Authorization-Code-Flow
Für Anwendungen mit interaktiver Nutzeranmeldung (z. B. eine Web-App im Namen eines angemeldeten Nutzers) wird der Authorization-Code-Flow verwendet. Der grobe Ablauf:
- Die Anwendung leitet den Nutzer auf den Authorization-Endpunkt von
Keycloak weiter (
response_type=code, mit Ihrerclient_idund einer registriertenredirect_uri). Für öffentliche Clients (ohne Secret) ist zusätzlich PKCE zu verwenden. - Nach erfolgreicher Anmeldung leitet Keycloak zurück zur
redirect_uriund übergibt einen einmaligen Authorization Code. - Die Anwendung tauscht den Code am Token-Endpunkt gegen ein Access-Token
(
grant_type=authorization_code) ein. - Das Access-Token wird – wie beim Client-Credentials-Flow – als Bearer-Token an die API gesendet.
Auch hier gelten die Voraussetzungen an roles und groups:
Der angemeldete Nutzer muss über die Rolle ROLE_SERVICEUSER (bzw. ROLE_USER)
und die passende TENANT_<name>-Gruppe verfügen.
Die konkreten Parameter (öffentlicher Client, erlaubte redirect_uris) legt der
Plattform-Betreiber für Ihre Anwendung fest.
Autorisierung
Nach erfolgreicher Authentifizierung entscheidet die Plattform anhand von drei Ebenen, was ein Aufrufer tun darf:
- Rollen – grobgranular, aus dem
roles-Claim des Tokens. - Tenant-Isolation – die mandantengetrennte Datenhaltung über den
groups-Claim (TENANT_<name>). - Zugriffsrechte auf Knotenebene – feingranular pro Knoten der Asset-Hierarchie.
Rollen
Die Rollen stehen im roles-Claim des Tokens. Für die REST-Schnittstelle sind
insbesondere relevant:
| Rolle | Bedeutung |
|---|---|
ROLE_USER | Standard-Lese-/Schreibzugriff (interaktive Nutzer) |
ROLE_SERVICEUSER | wie ROLE_USER, für nicht-interaktive Zugriffe (Client-Credentials) |
ROLE_ADMIN | administrative Endpunkte; umgeht die Prüfung auf Knotenebene |
ROLE_SERVICEADMIN | wie ROLE_ADMIN, für nicht-interaktive Zugriffe |
ROLE_CUSTOM_PANEL_TEMPLATE_CREATOR | Code und Vorlagen von Customizable Panels bearbeiten |
ROLE_HETIDA_DESIGNER_CONFIGURATOR | Konfiguration der hetida-designer-Integration |
ROLE_OPC_UA_USER | OPC-UA-spezifische Endpunkte |
Die meisten Endpunkte verlangen ROLE_USER oder ROLE_SERVICEUSER. Externe
Integrationen (Client-Credentials) erhalten typischerweise ROLE_SERVICEUSER
(siehe Voraussetzungen).
Tenant-Isolation
Jedes Token gehört zu genau einem Tenant, bestimmt durch den Eintrag
TENANT_<name> im groups-Claim. Die Datenhaltung ist mandantengetrennt (per
Row-Level-Security in der Datenbank): Ein Aufrufer sieht ausschließlich Daten
seines Tenants. Fehlt der Tenant-Eintrag oder sind mehrere TENANT_-Einträge
vorhanden, kann der Tenant nicht aufgelöst werden und der Zugriff schlägt fehl.
Zugriffsrechte auf Knotenebene
Über die Rollen hinaus wird der Zugriff auf einzelne Knoten der Asset-Hierarchie feingranular geprüft. Rechte werden pro Nutzer oder pro Gruppe auf Knoten vergeben und als CRUD-Berechtigungen ausgedrückt:
| Recht | Bedeutung |
|---|---|
C | Anlegen (Create) |
R | Lesen (Read) |
U | Ändern (Update) |
D | Löschen (Delete) |
- Lesende Endpunkte, die Listen oder Teilbäume der Hierarchie zurückgeben,
werden serverseitig gefiltert: Knoten ohne Leserecht (
R) erscheinen nicht in der Antwort. - Schreibende/löschende Zugriffe erfordern das entsprechende Recht (
Ubzw.D) auf dem Zielknoten. - Aufrufer mit
ROLE_ADMINoderROLE_SERVICEADMINumgehen diese Prüfung.
Die Vergabe von Knotenrechten erfolgt über die REST-Endpunkte der Tags
user-rights und group-rights (siehe
REST-Schnittstelle).
Fehlerbehandlung
| HTTP-Status | Ursache | Abhilfe |
|---|---|---|
401 Unauthorized | Kein, ungültiges oder abgelaufenes Token | Neues Token anfordern und den Authorization-Header prüfen. |
403 Forbidden | Token gültig, aber fehlende Rolle, falscher/kein Tenant oder fehlendes Zugriffsrecht auf dem Zielknoten | Prüfen, ob der Client/Nutzer ROLE_SERVICEUSER, die korrekte TENANT_<name>-Gruppe sowie das nötige Knotenrecht (R/U/D) besitzt. |