1
 
 
Profil
In deinem persönlichen Profilbereich kannst du den Status deiner Bewerbung einsehen, unvollständige Bewerbungen zwischenspeichern und aktuelle News und Events einsehen
13. Mai 2026

Sichere Service-Tokens mit Keycloak Token Exchange – automatisiert mit Terraform

Worum geht es in diesem Artikel?

In diesem Artikel erfährst du, wie sich Service-to-Service-Kommunikation in Microservice-Architekturen mit Keycloak Token Exchange sicherer gestalten lässt. Es wird gezeigt, wie nach dem OAuth-2.0-Standard gezielte Service-Tokens mit passender Audience und begrenzten Berechtigungen erzeugt werden – und wie sich die dafür nötige Keycloak-Konfiguration reproduzierbar mit Terraform automatisieren lässt.

In der modernen Softwareentwicklung, geprägt von Microservices und verteilten
Systemen, ist die sichere Authentifizierung und Autorisierung von Service-to-Service-Kommunikation von entscheidender Bedeutung. Diese Einführung beleuchtet, wie man robuste Service-Tokens mithilfe des Token-Exchange-Features von Keycloak absichert und die gesamte Infrastruktur mithilfe von Terraform effizient verwaltet. Keycloak dient hierbei als zentrale Identity- und Access-Management-Lösung, die es ermöglicht, Identitäten zu verwalten und den Austausch von Tokens für den Zugriff auf geschützte Ressourcen zu orchestrieren. Die Automatisierung dieser komplexen Konfigurationen mit Terraform gewährleistet dabei nicht nur Konsistenz und Reproduzierbarkeit, sondern auch eine agile Bereitstellung und Wartung der Sicherheitsinfrastruktur.

Token Exchange erklärt

Ein Token ist ein digitales Sicherheitszertifikat, das die für die Authentifizierung und Autorisierung erforderlichen elektronischen Schlüssel enthält. Diese Schlüssel legen die dem Benutzer gewährten Rechte und Zugriffsberechtigungen fest und ermöglichen so die sichere Anmeldung in digitalen Systemen.

Token Exchange bedeutet, einen bestehenden Token mit allgemeinen Berechtigungen gegen einen neuen Token zu ersetzen, der speziell auf die Anforderungen einer bestimmten Anwendung oder eines Services zugeschnitten ist. Dies entspricht dem Prinzip des „Need-to-know“, da im neuen Token nur die Berechtigungen enthalten sind, die für den jeweiligen Service erforderlich sind. Wird dieser Service kompromittiert, kann der neue Token nicht für die Autorisierung bei anderen Anwendungen oder Services verwendet werden. Der Token-Austausch erfolgt dabei über einen vertrauenswürdigen Client, ohne dass eine Benutzerinteraktion notwendig ist.

Keycloak als Basis für sichere Service-Kommunikation

Als zentrales Infrastruktur-Team stellen wir unseren Entwicklungsteams Keycloak bereit, um eine sichere und effiziente Anwendungsentwicklung im Kontext von Authentifizierung und Autorisierung zu ermöglichen. Keycloak übernimmt dabei die zentrale Benutzeridentitätsverwaltung. Innerhalb von Keycloak stellen wir unseren Entwicklungsteams eine isolierte Umgebung, einen sogenannten "Realm", zur Verfügung. In diesem Realm werden Benutzer, Anwendungen (Clients), Rollen und alle
zugehörigen Sicherheits- und Authentifizierungsdaten separat verwaltet.

Standard Token Exchange (RFC 8693)

Die Token-Exchange-Funktion ist schon seit Längerem in Keycloak verfügbar, aber bisher nur als Vorabversion. Mit der Veröffentlichung von Keycloak 26.2 wird der Standard Token Exchange nun offiziell unterstützt und ist vollständig mit dem OAuth 2.0 Token Exchange (RFC 8693) konform. Im Folgenden stelle ich dar, wie das Verfahren einfach mit Terraform aufgesetzt und per Skript genutzt werden kann. (Das Beispiel zeigt, wie sich Keycloak-Konfigurationen mit Terraform automatisiert und reproduzierbar umsetzen lassen. Mehr Grundlagen und Best Practices dazu findest du in unserer Terraform-Reihe „Skalierbare & zuverlässige Infrastructure-as-Code")

In diesem Beispiel starten wir einen lokalen Keycloak-Docker-Container. Ein Bootstrap-Skript erstellt darin einen Kunden-Realm "web-app" mit dem Client "terraform_client". Dieser Client ermöglicht es unseren Kunden, ihren Realm vollständig mit Terraform zu konfigurieren.

Hier ist ein Beispiel für einen id_token, den Keycloak ausstellt, nachdem du dich
erfolgreich angemeldet hast, und einen access_token, der dazu dient, dich bei APIs oder Ressourcen zu autorisieren:


id_token:
{
  "exp": 1763711539,
  "iat": 1763711239,
  "jti": "cdbd39ba-f49d-4dbe-98e9-17180f1ededb",
  "iss": "http://localhost:8080/realms/web-app",
  "aud": "frontend",
  "sub": "f817130a-3eea-4c7a-82cd-294d7c29810a",
  "typ": "ID",
  "azp": "frontend",
  "sid": "5d6e3640-8ed6-41e8-896d-415b0a4a949d",
  "at_hash": "4MUB7cfW_PdsSP2Bj0Y3Lg"
}

access_token:
{
  "exp": 1763711539,
  "iat": 1763711239,
  "jti": "onrtro:eb92b411-1619-45c0-91a4-2c2d6a681f26",
  "iss": "http://localhost:8080/realms/web-app",
  "aud": "api_gateway",
  "typ": "Bearer",
  "azp": "frontend",
  "sid": "5d6e3640-8ed6-41e8-896d-415b0a4a949d",
  "scope": "openid audience-scope"
}


Keycloak bietet die Möglichkeit, in den Token-Nutzdaten (Claims) zusätzlich zur Ausstellung (Issuer, "iss"), dem Benutzer ("sub") und der Ablaufzeit ("exp") eine Audience ("aud") anzugeben.

Diese Audience bestimmt, für welche Anwendung der Token bestimmt ist. Der Token ist somit nur für den Service gültig, welcher der angegebenen Audience entspricht, und kann nicht missbräuchlich für andere Services verwendet werden.

Zur Demonstration des Token-Exchange-Prinzips werden in dem Realm folgende Clients eingerichtet: ein Frontend-Client, ein API-Gateway-Client und drei Service-Clients (Booking-, Customer- und Order Service). Zusätzlich wird ein Admin-User mit den entsprechenden Berechtigungen für alle Client-Services angelegt.

Der Frontend-Client

Der Frontend-Client ist als PUBLIC konfiguriert, wodurch für die Authentifizierung kein Client Secret benötigt wird. Der Full Scope ist deaktiviert, da die erforderlichen Berechtigungen ausschließlich über die Audience zugewiesen werden:

resource "keycloak_openid_client" "frontend" {
    realm_id                     = data.keycloak_realm.web_app.id
    client_id                    = "frontend"
    name                         = "Frontend"
    access_type                  = "PUBLIC"
    direct_access_grants_enabled = true
    full_scope_allowed           = false
}

resource "keycloak_openid_audience_protocol_mapper" "audience_mapper" {
    realm_id                = data.keycloak_realm.web_app.id
    client_id               = keycloak_openid_client.frontend.id
    name                     = "audience-mapper-api"
    included_custom_audience = keycloak_openid_client.api_gateway.name
    add_to_access_token      = true
    add_to_id_token          = false
}

Der API-Gateway-Client

Der API Gateway Client wird als vertraulich (CONFIDENTIAL) und mit dem neuen Feature Standard Token Exchange angelegt. Das bedeutet, dass man sich mit der client_id  und dem client_secret anmelden muss.

resource "keycloak_openid_client" "api_gateway" {
  realm_id                     = data.keycloak_realm.web_app.id
  name                         = "api gateway"
  client_id                    = "api_gateway"
  client_secret                = "secret"
  description                  = "A API gateway client on the
destination realm"

  access_type                  = "CONFIDENTIAL"
  standard_token_exchange_enabled = true
}


Alle Service Clients sind über das Terraform-Modul service identisch als vertraulich konfiguriert.

Admin-Benutzer

Für das Demo-Skript wird ein Admin-Benutzer erstellt, dem alle angelegten Rollen zugewiesen werden:

resource "keycloak_user_roles" "user_roles" {
  realm_id   = data.keycloak_realm.web_app.id
  user_id    = keycloak_user.admin_user.id

  role_ids = concat(
    [for s in local.services : module.service[s.name].service_role_id],
    [keycloak_role.frontendAdmin.id]
  )
}

Demo-Skript

Frontend-Token holen

Ein Access-Token für den Benutzer admin mit Passwort wird vom Client frontend am Keycloak-Server angefordert:

TOKEN_FRONTEND=$(curl -s $KC_URL \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'username=admin' \
  -d 'password=realmAdmin' \
  -d 'grant_type=password' \
  -d 'client_id=frontend' \
  -d 'scope=openid' )


Der erhaltene Token wird dekodiert und relevante Felder werden angezeigt:

{
  "sub": null,
  "azp": "frontend",
  "aud": "api_gateway",
  "resource_access": null,
  "scope": "openid audience-scope"
}


Der Access-Token enthält azp als Authorized Party, sub als eindeutige ID des Users wird nicht mehr standardmäßig mitgeliefert, um den Token kleiner und effizienter zu halten. aud Audience ist hier nur api_gateway, da full scope nicht erlaubt wurde.

Token Exchange für Customer Service

Der Frontend-Token wird mit dem Client webapp_client gegen einen neuen Token mit der Audience CustomerService getauscht.

TOKEN_EXCHANGE=$(curl -s $KC_URL \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "api_gateway:secret" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  -d "subject_token=$TOKEN_FRONTEND" \
  -d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
  -d "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
  -d "audience=CustomerService" | jq -r .access_token)

Access-Token

{
  "sub": "0384647c-51d7-4999-a534-cb09c67dda1d",
  "azp": "api_gateway",
  "aud": "CustomerService",
  "resource_access": {
    "CustomerService": {
      "roles": [
        "write"
      ]
    }
  },
  "scope": "profile email"
}


Der Exchange-Token enthält jetzt die Audience CustomerService und erlaubt nur schreibenden Zugriff auf diesen Service. Mit sub ist es eindeutig einem Benutzer zuzuordnen.

Token Exchange für Booking Service

Der Frontend-Token wird mit dem Client webapp_client gegen einen neuen Token mit der Audience Booking Service getauscht.

TOKEN_EXCHANGE=$(curl -s $KC_URL \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "api_gateway:secret" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  -d "subject_token=$TOKEN_FRONTEND" \
  -d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
  -d "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
  -d "audience=BookingService" | jq -r .access_token)


In diesem Beispiel ist der BookingService die Audience, wodurch ein schreibender Zugriff auf diesen Service möglich ist.

{
  "sub": "0384647c-51d7-4999-a534-cb09c67dda1d",
  "azp": "api_gateway",
  "aud": "BookingService",
  "resource_access": {
    "BookingService": {
      "roles": [
        "write"
      ]
    }
  },
  "scope": "profile email"
}

Fazit

Mit dem aktuellen Keycloak Terraform Provider, der regelmäßig aktualisiert wird, lassen sich neue Funktionen wie das Standard-Token-Exchange-Verfahren einfach abbilden. Token Exchange bietet entscheidende Sicherheitsvorteile: Es ersetzt einen Token mit allgemeinen Berechtigungen durch einen spezifischen Token, der nur die für den jeweiligen Service erforderlichen Berechtigungen enthält (Need-to-know-Prinzip). Das minimiert im Falle einer Kompromittierung das Schadenspotenzial, da der Token nicht für andere Anwendungen oder Services verwendet werden kann.

Wir freuen uns über Feedback und Anregungen in den Kommentaren. ⬇️

Und wenn du dich weiter mit sicherer Infrastruktur und dem Schutz sensibler Informationen beschäftigen willst, lohnt sich im Übrigen auch ein Blick in unseren Artikel „Sensible Daten sicher verwalten mit HashiCorp Vault“.

Lust bei uns zu arbeiten?

9 Personen gefällt das
0Noch keine Kommentare
Kommentar schreiben
Hinterlasse uns hier deinen Kommentar und lass die Autor*innen wissen, wie dir der Artikel gefallen hat.
Antwort auf:  Direkt auf das Thema antworten

Geschrieben von

Andreas Nacke
Andreas Nacke
Senior IT Administrator

Ähnliche Beiträge

Gespeichert!

We want to improve out content with your feedback.

How interesting is this blogpost?

We have received your feedback.