Hallo zusammen,
(nicht nur) aus beruflichen Gründen interessiere ich mich für Identity und Access Management (IAM) Lösungen.
Ich habe Keycloak erfolgreich bei mir lokal installiert und beschriebe hier einen einfachen Proof of Concept. Dabei habe ich mich sehr nahe an dem guten Video von Milan Jovanović gehalten:
Was ist Keycloak
Stellt euch vor, wir müssten bei jeder App einen Benutzer und Passwort anlegen und ein Administrator müsste für alle User bestimmen, wer was darf. Dieser ganze Prozess ist in zentrale IAM Systeme ausgelagert. Keycloak ist ein Teil davon, nämlich der, der die Authentifizierung (bist du du?) übernimmt (ähnlich wie bei Google-Authentication).
Keaycloak ist somit eine IAM Software, die die Verwaltung von Accounts und deren Zugriff auf Applikationen regelt. Der Focus liegt dabei beim Access Management und Single Sign On (SSO).
Ein (wie man sieht) KI generiertes Bild von Bing
Installation von Keycloak
Voraussetzung: Podman (oder Docker) läuft auf der lokalen Maschine. Installation z.B. hier.
Man erstellt ein Verzeichnis und dort in einer Konsole führt man folgenden Befehl aus: (Ich habe den Port auf 8081 geändert, da bei mir 8080 schon mit Midpoint belegt ist):
podman run -p 8081:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:21.0.2 start-dev
Und nach zwei Minuten (später: wenige Sekunden) läuft die Sache im Browser:
Einen Realm erstellen
Ein Realm ist ein abgeschotteter Bereich, in dem Einstellungen für User, Clients, Applikationen,... vorgenommen werden. Auf Keycloak ist standardmäßig schon ein Realm installiert, nämlich der für den Amdin-Zugriff auf sich selbst. Wir erzeugen nun einen neuen Realm, durch Klick links oben auf das Dreieck neben master, Create Realm und geben einen Realm-Namen ein:
In dem Realm erzeugen wir einen User durch klicken auf Users/create User. Bei "Required User Actions" tragen wir erst mal nichts ein.:
Das Passwort müssen wir aber setzen:
Der User kann sich nun anmelden an http://localhost:8081/realms/AchimsFirstRealm/account
Wenn folgendes zu sehen ist, dann hat der Userzugriff auf das lokale Realm schon mal geklappt:
Man könnte hier noch einige Informationen hinzufügen, wir lassen es aber erst mal so.
Erstellung eines Clients
Ein Client ist eine Konfiguration, die wir für die Anbindung von Keycloak mit einer Applikation brauchen. Im folgenden Beispiel erzeugen wir so eine Client-Konfiguration:
Eine Applikation an Keycloak anbinden
Jetzt wird es spannend. Wir wollen nun eine Applikation an Keycloak anbinden. D.h. diese App verwaltet die Benutzer nicht selber sondern nutzt Keycloak zur Authentifizierung und anschließendem Zugriff. Dazu sendet die App eine Abfrage an den Keycloak-Server. Wenn dort die Authentifizierung klappt, kommt ein Token zurück, dass diese Authentifizierung bestätigt und die App kann weitermachen.
Auf der Seite https://keycloak.org/app kann man so eine Mini-App so konfigurieren, dass sie mit meinem lokalen Keycloak spricht:
Nach der Konfiguration erscheint ein Sign in-Button. Ich habe mal im Browser auf F12 gedrückt um den Netzwerktraffik zu beobachten:
Sobald ich auf "sign in" klicke, werde ich zu meinem lokalen Keycloak weiter geleitet. Dort wird mir die Eingabemaske zur Verfügung gestellt.
Wenn ich jetzt auf "sign in" drücke, wird bei mir lokal auf dem Keycloak überprüft, ob Username und Passwort zusammenpassen. Da das hier der Fall ist, wird ein Token zurück an die App geschickt und dort erscheint dann die nächste Seite, in diesem Fall eine Logout Maske, mit einem Gruß "Hello, Achim Mertens" (Der Benutzername wurde also auch von Keycloak an die App übermittelt).
Was wird denn da übertragen?
Schauen wir uns den Netztraffic etwas genauer an. Zuerst wird von der App eine Anfrage an Keycloak gesendet. Wir schauen uns den Anfrage-Cookie und dort die Keycloak-Identity an
Dieser "eyjh...." String ist ein sogenanntes JSON Web Token und kann mit einem Dekodierer wie https://jwt.io/ entschlüsselt werden:
Als Antwort kommt erst mal ein bischen Allgemeininfo:
und weitere Daten, die dann der Browser zu einer neuen Webseite aufsetzt, also die Abfragemaske erstellen.
Spannender ist die zweite POST-Anfrage, nämlich da, wo wir die Maske ausgefüllt haben und Anmeldename und Passwort übergeben:
Wir erhalten jetzt nämlich einen Access- und einen ID-Token:
Der Inhalt des Access Token sieht so aus:
Und der vom ID-Token so:
Das Expiration Date (exp) kann man auch noch entschlüsseln, wenn man will:
https://www.epochconverter.com/
Mit diesen Informationen kann die App nun weiter arbeiten.
Der Access Token dient der Autorisierung und gewährt Zugriff auf geschützte Ressourcen wie APIs oder Server.
Der ID-Token dient der Authentifizierung und enthält Informationen über die Identität des Benutzers
Im ID-Token wird auch eine Signatur mitgeschickt, also unser Keycloak setzt einen Stempel auf den Inhalt, den er verschickt. Hier in unserem Fall ist die Signatur ungültig, weil wir ja einen lokalen ID-Provider haben, der nicht öffentlich zertifiziert ist, also keiner den Stempel kennt.
Mithilfe der Signatur kann und sollte die App überprüfen, ob der Benutzer wirklich von dem ID-Provider kommt, dem wir vertrauen:
Wie es weitergeht
Hier ist eine schöne Zusammenfassung aus dem Youtube-Video, wie das Zusammenspiel zwischen dem User, dem Identity Broker Keycloak und einer Apllikation, die via API erreichbar ist, funktioniert.
Keycloak kann noch viel mehr, aber hier endet erst mal für mich die Reise, da ich das Prinzip verstehen wollte. Ich könnte noch über das Protokoll OpenID-Connect oder Secrets weiter recherchieren, mache das aber evtl. später. Was mich als nächstes interessiert, ist das Zusammenspiel zwischen LDAP (Verzeichnisserver), Midpoint (IAM Server, Identity Provider, Rollenshop) und Keycloak (Access Provider).
Also, stay tuned.
Gruß, Achim
Spannend zu lesen, danke für den Artikel. Ich befinde mich mittlerweile immer öfter auf der anderen Seite solcher IDPs wie Keycloak oder Azure und schreibe Applikationen, die diese anbinden zwecks eines SSO-Logins. Eine Frage, die ich aber bisher nicht abschliessend beantworten kann, wäre:
Was ist der gängige Weg, den id_token/access_token/refresh_token an Drittsysteme zu geben. Ich speichere diese üblicherweise immer in Cookies auf der Hauptdomain, das setzt jedoch voraus, dass die Drittsysteme auf Subdomains laufen müssen, damit diese Zugriff auf die entsprechenden Cookies haben. Eventuell hast du da eine bessere Idee?
Hallo @stubenhocker, was der beste Weg ist weiß ich nicht. Ich bin auch eher noch im Experiemntierstadium. Bei mir war es bisher so, dass ich die Cookies über einen POST Request übermittel. Also entweder "von Hand" (in einer Shell oder Postman), oder via Script. Bei Drittsystemem tritt dieses CORS Problem auf, damit habe ich auch immer gekämpft. Außer dem Tipp eine KI zu fragen (z.B. https://v0.dev), kann ich dir wahrscheinlich nicht viel weiter helfen.
Gruß, Achim
#hive #posh
!PIZZA
$PIZZA slices delivered:
@thehockeyfan-at(2/5) tipped @achimmertens