Keycloak als Identity Provider

Keycloak[1] ist ein "Open Source Identity and Access Management", das als Identity Provider(IdP) zur Benutzer-Authentifizierung und Autorisierung verwendet werden kann.

Im Folgenden wird beschrieben, wie Sie das BPC mit Keycloak als Identity Provider konfigurieren.

Voraussetzung

Sie haben Keycloak installiert und besitzen administrativen Zugriff auf Keycloak und BPC.

Sie sollten möglichst immer die neuste Version von Keycloak einsetzen, um Sicherheitsrisiken zu vermeiden.

Konfiguration Keycloak

Legen Sie bitte ein Realm für das BPC an oder nutzen Sie einen bestehenden Realm, den Sie evtl. bereits für andere Anwendungen nutzen.

Es wird davon abgeraten den Realm master zu verwenden. Diese sollte ausschließlich für administrative Keycloak Zugänge genutzt werden.

Ein Skript, das die folgenden Punkte per API konfiguriert, finden Sie im Abschnitt Skript für automatische Einrichtung.

Client anlegen

Damit das BPC mit dem Keycloak kommunizieren kann, muss ein Client angelegt werden.

  1. Stellen Sie sicher, dass Sie den richtigen Realm ausgewählt haben.

  2. Wählen Sie "Clients" auf der linken Seite

  3. Erzeugen Sie über "Create client" einen neuen Client

  4. Wählen Sie "OpenID Connect" als "Client type"

  5. Vergeben Sie eine Client-ID, wie z.B. bpc.
    Diese muss später mit der Konfiguration client_id im BPC übereinstimmen.

  6. Aktivieren Sie "Client authentication". In älteren Keycloak-Versionen entspricht das dem Access-Type "confidential".

  7. Tragen Sie unter "Valid redirect URIs" die URL ihres BPCs ein. Z.B. "https://bpc.example.com/"

  8. Speichern Sie den Client

  9. Im Tab "Passwörter"(oder "Credentials") können Sie das Client secret einsehen (und auch ändern).
    Dieses muss später mit der Konfiguration client_secret im BPC übereinstimmen.

BPC Rollen anlegen

Um BPC Administratoren ernennen zu können, benötigen Sie die Rolle bpcadmin.

  1. Wählen Sie "Realm-Rollen" auf der linken Seite

  2. Legen Sie über "Create role" die Rolle bpcadmin an.

BPC Administrator anlegen oder zuweisen

Damit ein Benutzer im BPC Administrator ist, benötigt er die Rolle bpcadmin.

  1. Wählen Sie "Benutzer" auf der linken Seite

  2. Legen Sie über "Benutzer hinzufügen" einen neuen Benutzer an oder wählen Sie einen bestehenden Benutzer aus

  3. Weisen Sie dem Benutzer die Rolle bpcadmin zu

Konfiguration BPC

Im BPC muss Keycloak unter den Backend Connections als Identity Provider angelegt und anschließend in den Core Services Einstellungen als zu verwendender Identity Provider festgelegt werden.

Beim Start des BPC werden automatisch Backend Connections angelegt, die für den Keycloak genutzt werden können. Diese enthalten eine passende Platzhalter-Konfiguration und haben die Namen Keycloak und OIDC. Siehe auch Identity Provider Keycloak vs. OIDC

Identity Provider Keycloak vs. OIDC

Sie haben die Möglichkeit Keycloak in zwei verschiedene Varianten (IdentityProvider OpenID Connect (OIDC) oder Keycloak) anzubinden. In beiden Varianten erfolgt die eigentliche Authentifizierung über das OpenID Connect Protokoll. In der reinen OpenID Connect (OIDC) Variante erfolgt die Benutzer Administration ausschließlich im Keycloak. Wählen Sie "Keycloak" kann die im BPC integrierte Benutzerverwaltung / Identity Manager verwendet werden.

Bis einschließlich BPC 4.2.4 muss bei der Verwendung des Typs Keycloak zusätzlich ein Keycloak Admin-User hinterlegt werden. Siehe dafür die Dokumentation BPC 4.1. Diese gilt an dieser Stelle auch bis Version 4.2.4.

Spezifische Konfiguration der Backend Connection

Folgende für diesen Identity Provider spezifischen Einstellungen finden sich an der Backend Connections vom Typ identity_provider. Für die allgemeine Konfiguration der Backend Connections vom Typ identity_provider siehe Allgemeine Identity Provider Konfiguration.

Setting (Key) Gruppe Wert Beschreibung

IdentityProvider
(identityProvider)

config

Keycloak oder OpenID Connect (OIDC)

Keycloak bzw. OIDC für die Backend Connection als IdP festlegen.
Siehe auch Identity Provider Keycloak vs. OIDC

IdentityProvider_URL
(identityProvider.url)

config

`https://localhost:8080/auth/realms/bpc/.well-known/openid-configuration`

OIDC Discovery Endpoint

IdentityProvider_Configuration
(identityProvider_configuration)

config

{
    "post_authentication_redirect_uri": "http://localhost:8181/",
    "claim_name_roles": "resource_access.bpc.roles,realm_access.roles",
    "scope": "openid profile email address phone roles",
    "client_secret": "bpc-test-only",
    "post_logout_redirect_uri": "http://localhost:8181",
    "client_id": "bpc"
}

Die Konfiguration für den Keycloak Zugriff. Die URLs müssen hier entsprechend dem BPC und dem Keycloak angepasst werden.
Siehe OIDC / Keycloak Verbindungsparameter

OIDC / Keycloak Verbindungsparameter

In dem JSON Setting identityProvider_configuration können folgende Parameter konfiguriert werden:

Für BPC Installationen bis einschließlich Version 4.2.4 sind weitere Konfigurationen nötig. Siehe dafür die Dokumentation BPC 4.1. Diese gilt an dieser Stelle auch bis Version 4.2.4.

Attribut Beispielwert Beschreibung

post_authentication_redirect_uri

An diese Adresse wird der Benutzer weitergeleitet, nachdem ein Login ausgeführt wurde.
Diese URL muss im Keycloak Client erlaubt sein und sollte auf das BPC zeigen.

claim_name_roles

realm_access.roles

Komma separierte Liste aller Claim Namen aus denen die Rollen des Benutzers extrahiert werden.

claim_name_organisations

organisations

Komma separierte Liste aller Claim Namen aus denen die Organisationen des Benutzers extrahiert werden.

claim_name_rights

rights

Komma separierte Liste aller Claim Namen aus denen die Rechte des Benutzers extrahiert werden.

scope

openid profile email address phone roles

OIDC Scopes die bei der Authentisierung beim OIDC Provider angefragt werden. Werden Scopes angefragt, die es nicht gibt oder für die der Client nicht berechtigt ist, kann es zu Fehlern bei der Authentifizierung kommen.

client_id

bpc

ID des im OIDC Provider konfigurierten Clients über den der Zugriff erfolgen soll.

client_secret

bpc-test-only

Secret für die Authentifizierung des Clientzugriffs.

post_logout_redirect_uri

An diese Adresse wird der Benutzer weitergeleitet, nachdem ein Logout ausgeführt wurde.
Diese URL muss im Keycloak Client erlaubt sein.

metadata_discovery_uri

[
    {
       "pattern": ".*extern.*",
       "uri": "https://keycloak.extern.de/auth/realms/bpc/.well-known/openid-configuration"
    },
    {
       "pattern": ".*intern.*",
       "uri": "https://keycloak.intern.de/auth/realms/bpc/.well-known/openid-configuration"
    }
]

BPC Integration

Sollten Sie an der Einstellung identityProvider den Typ Keycloak gewählt haben, stehen Ihnen verschiedene Integrationen bereit.

Das BPC bietet Zugriff auf verschiedene Funktionen der Benutzerverwaltung durch die integrierte Benutzerverwaltung.

Über das User Account Menu Plugin können auch diverse Aktionen gegenüber dem Keycloak vom Benutzer ausgeführt werden.

Skript für automatische Einrichtung

Für Entwicklungs- und Testumgebungen kann das folgende Skript genutzt werden. Dieses Skript geht gegen die Admin REST API von Keycloak und richtet einen neuen Realm bpc ein. Dieser ist anschließend so konfiguriert, dass er mit dem vorkonfiguriertem Identity Provider Keycloak (ID: idp_keycloak) funktioniert.

Die Konfiguration der vom BPC initial bereitgestellten Backend Connection Keycloak (ID: idp_keycloak) wurde im BPC 4.2.5 angepasst, so das diese zu diesem Beispiel passt. Sollten Ihr BPC initial mit einer Version < 4.2.5 installiert worden sein, dann können Sie diesen Identity Provider aus den Backend Connections löschen. Nach einem Neustart wird dieser erneut mit den neuen Standardeinstellungen wiederhergestellt. Alternativ können Sie das Skript anpassen (z.B: die ID den Clients).

Das Skript kann z.B. genutzt werden, wenn man temporär zum Testen ein Keycloak via Docker startet.

docker run --rm -p 8443:8443 -p 8080:8080 \
    -e KEYCLOAK_ADMIN=admin \
    -e KEYCLOAK_ADMIN_PASSWORD=admin \
    -e KC_FEATURES=token-exchange \
    quay.io/keycloak/keycloak start-dev --hostname=localhost

Die Variablen des Skriptes sollten nach Bedarf angepasst werden. Es ist jedoch nicht nötig ADMIN_USER und ADMIN_PASSWORD zu setzen. Diese beiden Variablen werden beim Start über das Terminal abgefragt.

Konfigurationsskript createBpcRealm.sh
#!/bin/bash

# Keycloak Server URL und Admin Credentials
KEYCLOAK_URL="http://localhost:8080"
KEYCLOAK_REALM="master"
ADMIN_USER=""
ADMIN_PASSWORD=""

# Neue Realm-, Client- und Benutzer-Konfiguration
NEW_REALM="bpc"
NEW_CLIENT="bpc"
CLIENT_SECRET="bpc-test-only"
NEW_ROLE="bpcadmin"
BPC_USER="bpcuser"
BPC_ADMIN="bpcadmin"

# Benutzer-Daten
BPC_USER_FIRSTNAME="BPC"
BPC_USER_LASTNAME="User"
BPC_USER_EMAIL="bpcuser@example.com"

BPC_ADMIN_FIRSTNAME="BPC"
BPC_ADMIN_LASTNAME="Admin"
BPC_ADMIN_EMAIL="bpcadmin@example.com"

# Redirect-URL für den Client
REDIRECT_URL="http://localhost*"

# Funktion zur Eingabe von Benutzername und Passwort
read -p "Gib den Keycloak Admin Benutzernamen ein: " ADMIN_USER
read -s -p "Gib das Keycloak Admin Passwort ein: " ADMIN_PASSWORD
echo ""

# Abrufen eines Tokens vom Keycloak-Server
TOKEN=$(curl -s \
  -d "client_id=admin-cli" \
  -d "username=$ADMIN_USER" \
  -d "password=$ADMIN_PASSWORD" \
  -d "grant_type=password" \
  "${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token" | jq -r .access_token)

# Prüfen, ob das Token erfolgreich abgerufen wurde
if [ -z "$TOKEN" ]; then
  echo "Fehler beim Abrufen des Tokens. Überprüfe Benutzername/Passwort und Keycloak-URL."
  exit 1
fi

# Realm "bpc" erstellen mit Internationalisierung
# Für Login Theme die folgende Zeile mit aufnehmen
# "loginTheme": "theme-id",
echo "Erstelle den Realm '${NEW_REALM}' mit Login-Theme 'foo-theme' und Internationalisierung..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "realm": "'"${NEW_REALM}"'",
    "enabled": true,
    "internationalizationEnabled": true,
    "supportedLocales": ["en", "de"],
    "defaultLocale": "en"
  }'

# Client "bpc" erstellen
echo "Erstelle den Client '${NEW_CLIENT}' im Realm '${NEW_REALM}' mit Redirect-URL '${REDIRECT_URL}'..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/clients" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "'"${NEW_CLIENT}"'",
    "secret": "'"${CLIENT_SECRET}"'",
    "enabled": true,
    "redirectUris": ["'"${REDIRECT_URL}"'"],
    "directAccessGrantsEnabled": true
  }'

# Realm-Rolle "bpcadmin" erstellen
echo "Erstelle die Realm-Rolle '${NEW_ROLE}'..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/roles" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "'"${NEW_ROLE}"'"
  }'

# Benutzer "bpcuser" erstellen
echo "Erstelle den Benutzer '${BPC_USER}'..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "'"${BPC_USER}"'",
    "firstName": "'"${BPC_USER_FIRSTNAME}"'",
    "lastName": "'"${BPC_USER_LASTNAME}"'",
    "email": "'"${BPC_USER_EMAIL}"'",
    "enabled": true,
    "credentials": [{
      "type": "password",
      "value": "'"${BPC_USER}"'",
      "temporary": false
    }]
  }'

# Benutzer "bpcadmin" erstellen
echo "Erstelle den Benutzer '${BPC_ADMIN}'..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "'"${BPC_ADMIN}"'",
    "firstName": "'"${BPC_ADMIN_FIRSTNAME}"'",
    "lastName": "'"${BPC_ADMIN_LASTNAME}"'",
    "email": "'"${BPC_ADMIN_EMAIL}"'",
    "enabled": true,
    "credentials": [{
      "type": "password",
      "value": "'"${BPC_ADMIN}"'",
      "temporary": false
    }]
  }'

# Benutzer-ID des Benutzers "bpcadmin" abrufen
BPC_ADMIN_ID=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/users?username=${BPC_ADMIN}" \
  -H "Authorization: Bearer $TOKEN" | jq -r '.[0].id')

# Rollen-ID der Rolle "bpcadmin" abrufen
ROLE_ID=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/roles/${NEW_ROLE}" \
  -H "Authorization: Bearer $TOKEN" | jq -r '.id')

# Rolle "bpcadmin" dem Benutzer "bpcadmin" zuweisen
echo "Weise die Rolle '${NEW_ROLE}' dem Benutzer '${BPC_ADMIN}' zu..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/users/${BPC_ADMIN_ID}/role-mappings/realm" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "id": "'"${ROLE_ID}"'",
      "name": "'"${NEW_ROLE}"'"
    }
  ]'

# Abrufen der Scope-ID für "profile" im Realm "bpc"
echo "Rufe die Scope-ID für 'profile' im Realm '${NEW_REALM}' ab..."
PROFILE_SCOPE_ID=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/client-scopes" \
  -H "Authorization: Bearer $TOKEN" | jq -r '.[] | select(.name == "profile") | .id')

# Prüfen, ob die Scope-ID für "profile" gefunden wurde
if [ -z "$PROFILE_SCOPE_ID" ]; then
  echo "Fehler: Der Scope 'profile' wurde im Realm '${NEW_REALM}' nicht gefunden."
  exit 1
fi

# Mapper "Impersonator User ID" zum "profile" Scope hinzufügen
echo "Füge dem Scope 'profile' den Mapper 'Impersonator User ID' hinzu..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/client-scopes/${PROFILE_SCOPE_ID}/protocol-mappers/models" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Impersonator User ID",
    "protocol": "openid-connect",
    "protocolMapper": "oidc-usersessionmodel-note-mapper",
    "config": {
      "user.session.note": "IMPERSONATOR_ID",
      "id.token.claim": "true",
      "introspection.token.claim": "true",
      "access.token.claim": "true",
      "claim.name": "impersonator.id",
      "jsonType.label": "String"
    }
  }'

# Mapper "Impersonator Username" zum "profile" Scope hinzufügen
echo "Füge dem Scope 'profile' den Mapper 'Impersonator Username' hinzu..."
curl -s -X POST "${KEYCLOAK_URL}/admin/realms/${NEW_REALM}/client-scopes/${PROFILE_SCOPE_ID}/protocol-mappers/models" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Impersonator Username",
    "protocol": "openid-connect",
    "protocolMapper": "oidc-usersessionmodel-note-mapper",
    "config": {
        "user.session.note": "IMPERSONATOR_USERNAME",
        "id.token.claim": "true",
        "introspection.token.claim": "true",
        "access.token.claim": "true",
        "claim.name": "impersonator.username",
        "jsonType.label": "String"
    }
  }'

echo "Fertig!"

Die Ausführung des Skriptes erfolgt auf eigene Gefahr. Für die Funktion wird keine Gewährleistung übernommen.

In dem Skript wird für den Client ein unsicheres Secret gesetzt. Dieses sollte so nie in produktiven Umgebungen genutzt werden.


1. Keycloak ist ein Warenzeichen von The Linux Foundation.

Keywords: