Keycloak Funktionsweise

NicoDeluxe

NicoDeluxe

Top Contributor
Hallo zusammen,

ein User hat mir in einem anderen Thread einen tollen Tipp gegeben, mir mal Keycloak anzusehen um meine Spring/Vaadin Anwendung abzusichern.

Jetzt hab ich eine grundsätzliche Verständnisfrage:

Wie ist das vorgehen?
Angenommen ich möchte einen zentralen Auth-Server und meine Software wird von 100 Kunden auf 100 Servern verwendet.

Keycloak läuft zb auf einer Subdomain zentral zb auth.domain.de der User logged sich dort ein und wird an seinen Server weitergeleitet. Wie genau kapiert Spring jetzt, dass der User Zugriff gemäß der Spring Secruity Config hat und Seite /admin aufrufen darf zb.

Was hat das mit den Token auf sich? Wäre toll wenn mir jemand etwas Licht ins dunkel bringen kann :)
 
kneitzel

kneitzel

Top Contributor
Das Beispiel, das dir gestern schon gegeben wurde, hast Du Dir mal angesehen?

Da wird ein einfaches Beispiel aufgebaut und kurz erläutert.

Wenn Du 100 Kunden hast, dann will ja jeder Kunde seine eigenen User haben -> Realms. Dann hast Du für jeden Kunden einen Realm und damit sieht er die anderen Kunden nicht und so ... Und Du kannst dann auch User Admins beim Kunden einrichten - die dürfen dann den realm verwalten.

Und nein - der User meldet sich nicht direkt auf auth.domain.de an. Der User geht ganz normal auf die Server mit der Applikation. Die Autorisierung macht dann die Applikation (über auth.domain.de) Wenn die Autorisierung erfolgreich war, bekommt die Spring Boot Applikation für den User zwei Token. Das eine ist das Token, das den angemeldeten User identifiziert und das andere ist ein Token, mit dem die Gültigkeit verlängert werden kann bzw. ein neues Tokenpaar bekommen werden kann.

In dem Beispiel findet die Konfiguration der Rechte in SecurityConfig statt:
Java:
        http.authorizeRequests()
          .antMatchers("/customers*")
          .hasRole("user")
          .anyRequest()
          .permitAll();
==> Alles unter /customers darf aufgerufen werden, wenn der User die Rolle "user" hat.
 
NicoDeluxe

NicoDeluxe

Top Contributor
Ich hab grad mit einem Kollegen was am Wickel, das Tut schauen wir uns dann unbedingt an.

Was mir noch unklar ist, um das Erneuern des Token kümmert sich Spring dann selber oder wer übernimmt das aktualisieren des Token?

Aus deinem Code verstehe ich richtig, dass ich dann in Keycloak (per REST API) einen Benutzer anlegen kann mit der Rolle "user", der dann nur auf /customers kommt.

Meine Idee ist es wie folgt: Kunde bestellt über Webseite ein Paket bei uns ,unser System setzt einen Server auf mit dem Programm, legt einen Adminuser bei Keycloak an und der User kann los legen. Irgendwelche Funktionen, Passwort zurück setzen wird dann auch alles über KC gehen

Das klingt total genial irgendwie und spart Arbeit und ist vermutlich sicherer als wenn man es selber zusammen wurschtelt ohne wirklich zu wissen, was man da macht.
 
kneitzel

kneitzel

Top Contributor
Also in Keycloak legst du nur Rollen fest. Was diese Rollen in der Spring Applikation dürfen interessiert Keycloak nicht.

Keycloak dient nur dazu, die Anmeldung zu prüfen. Die Rollen sind nur Beiwerk...
 
NicoDeluxe

NicoDeluxe

Top Contributor
So hab ich es verstanden, ja. Was wer aufrufen darf wird in der Spring Security Config festgelegt (mittels der Rollen)
 
H

httpdigest

Top Contributor
Und nein - der User meldet sich nicht direkt auf auth.domain.de an. Der User geht ganz normal auf die Server mit der Applikation. Die Autorisierung macht dann die Applikation (über auth.domain.de)
Das ist eine Möglichkeit, die in OAuth 2.0 "Resource Owner Password Credentials Grant"-Flow genannt wird, der aber für Webanwendungen und mobile Apps nicht empfohlen wird, da hier der userseitigen Anwendung vertraut werden muss, mit den User-Credentials sicher umzugehen.
Sicherer ist der "Authorization Code Flow with Proof Key for Code Exchange"-Flow, bei welchem sich der User (sowohl bei einer Webanwendung als auch bei einer mobile App) per Browser auf auth.domain.de (bzw. einer von Keycloak bereitgestellten Seite) einlogged und dein eigenes Frontend bekommt hier nur noch einen Cookie zurückgesendet und auch niemals das Access oder Refresh Token. Ein sehr grosser Vorteil von diesem Flow ist, dass man in Keycloak auch beliebige Dritt-Identityprovider integrieren kann (mache ich tatsächlich gerade bei einem Kundenprojekt). Zum Beispiel brauchst du dann keinen eigenen User/Passwort mehr in Keycloak pflegen, sondern kannst deine User sich einfach per deren eventuell vorhandenen Google/Facebook/Twitter/GitHub/...-Account einloggen lassen und dann hast du zumindest deren Identität, diese werden dann in Keycloak auf User gemapped und du kannst dann Metainformationen zu den Usern hinterlegen. Hier spart man sich also noch eine "Passwort vergessen"-Funktionalität, weil du selbst ja das Passwort gar nicht speicherst (bzw. natürlich ja einen Hash davon). Natürlich kannst du per Keycloak Webfrontend immer noch einen Fallback mit Username/Passwort einbauen, wenn du Social Identity Provider Logins nicht möchtest, oder der User das nicht hat/kann/darf/will.
 
sascha-sphw

sascha-sphw

Bekanntes Mitglied
Um das Paket noch abzurunden, es ist sogar möglich den LDAP oder Active Directory vom Kunden als externe Benutzerdatenbank anzubinden, falls der Kunde seine eigene Benutzerdatenbank bereits hat und wiederverwenden möchte. Ich habe das selbst noch nicht gemacht, aber in den Vorträgen sah das immer recht einfach aus.
 
H

httpdigest

Top Contributor
Japp, Keycloak unterstützt "Federation" per OpenID Connect (für alle Social Identity Provider und jeden anderen, der OIDC unterstützt) und auch SAML 2.0 (was für ActiveDirectory genutzt wird).
 
NicoDeluxe

NicoDeluxe

Top Contributor
Wow danke euch, klingt mega umfangreich. Nun hab ich den Plan weitergedacht, dass jeder Kunde einen eigenen REALM bekommt um die Unternehmen zu trennen. Allerdings muss ich in den application.properties fields den realm Namen angeben. Hab es jetzt noch nich weiter getestet aber vermute, dass ich je Firma ein realm vergessen kann, da sonst überall die properties geändert werden muss.

oder sollte lieber auf jeden Kundenserver ein eigenes Keycloak? Find ich aber irgendwie unpraktisch.
 
H

httpdigest

Top Contributor
Ich hab da eine Komponente noch etwas verschwiegen: Meist hat man ja noch einen Edge Server/Proxy/Gateway (z.B. Ambassador) oder Load Balancer (z.B. AWS's Application Load Balancer) vor seine ganze Anwendungslandschaft geschaltet, die dann auch meist (zumindest im Falle dieser beiden) OpenID Connect Authentifizierung mit Authorization Code Flow unterstützen. :)
Ein solcher Edge Server / Gateway hat dann den Vorteil, dass man die Authentifizierung nicht in jeder bereitgestellten Anwendung erneut implementieren bzw. konfigurieren muss, sondern kann das dem Edge Server überlassen.
 
mihe7

mihe7

Top Contributor
Ich hab da eine Komponente noch etwas verschwiegen: Meist hat man ja noch einen Edge Server/Proxy/Gateway (z.B. Ambassador) oder Load Balancer (z.B. AWS's Application Load Balancer) vor seine ganze Anwendungslandschaft geschaltet, die dann auch meist (zumindest im Falle dieser beiden) OpenID Connect Authentifizierung mit Authorization Code Flow unterstützen. :)
Ein solcher Edge Server / Gateway hat dann den Vorteil, dass man die Authentifizierung nicht in jeder bereitgestellten Anwendung erneut implementieren bzw. konfigurieren muss, sondern kann das dem Edge Server überlassen.
Aha, da kommen wir der Sache schon näher :)
 
H

httpdigest

Top Contributor
Interessant hier wäre jetzt natürlich die eigentliche "Systemarchitektur" von @NicoDeluxe , also: welche Anwendung(en) sollen abgesichert werden, wie findet ein Aufruf vom Nutzer zum Server? Ist die Anwendung multitenantfähig oder ein Deployment pro Kunde mit jeweils für den Kunden spezifischen Settings pro Deployment? etc. etc.
 
NicoDeluxe

NicoDeluxe

Top Contributor
Hey, hab das jetzt wie folgt eingebaut:

ein zentraler AuthServer mit Keycloack, ein Kundendeployment welches auf einem server läuft über Url kunde1.domain.de

Nun lege ich für jeden Kundenserver einen Client in KC an (redirect URL nach login dann kunde1.domain.de) und einen Admin-User für diesen Client. Wir geben Rollen vor, zb Rolle "Buchhaltung", "Lager" der Admin kann dann weitere User für seinen Client anlegen und die Rollen entsprechend vergeben.

Somit ist jedes Deployment (Server) von anderen Kunden getrennt und jeder Kunde kann sich User anlegen wie er möchte und die Rechte vergeben wie er will.

Problem ist, wenn es mal Netzwerkprobleme gibt. Dann funktioniert auf keinem Server ein Login (dafür gibts aber sicher auch ne Lösung).

Noch ein Problem ist, dass man in der application.properties die clientId angeben muss. Kann man das in Code auslagern, sodass das flexibler wird ohne jedesmal die application.properties anfassen zu müssen? Denn das Aufsetzen eines Servers wird automatisch funktionieren, da will keiner manuell nachher noch irgendwas rumbasteln. Wenn wir einen Server per API bestellen, geben wir einen Hostnamen vor, der ist dann auch die clientID. Wenn man nun keycloak.resource in den Code bringt, könnten wir beim Starten der App die hosts Datei vom OS auslesen, damit das Programm weiß auf welchen Client es sich in KC connecten muss
 
H

httpdigest

Top Contributor
Noch ein Problem ist, dass man in der application.properties die clientId angeben muss. Kann man das in Code auslagern, sodass das flexibler wird ohne jedesmal die application.properties anfassen zu müssen? Denn das Aufsetzen eines Servers wird automatisch funktionieren, da will keiner manuell nachher noch irgendwas rumbasteln. Wenn wir einen Server per API bestellen, geben wir einen Hostnamen vor, der ist dann auch die clientID. Wenn man nun keycloak.resource in den Code bringt, könnten wir beim Starten der App die hosts Datei vom OS auslesen, damit das Programm weiß auf welchen Client es sich in KC connecten muss
Sowas löst man üblicherweise per Umgebungsvariablen und besser noch: Per Containerorchestrierung (z.B. Kubernetes) und Infrastructure as Code, wo du dann Deployment-Descriptoren / Module hast, in denen festgelegt ist, welches Containerimage (deine Anwendung + OS) zu starten ist und mit welchen Konfigurationsparametern (z.B. Vault Secrets und eben Umgebungsvariablen) das zu starten ist. Man sollte, wie du schon sagtest, da nicht auf einem "Server"/Host rauf SSHen müssen und dann noch irgendwelche Config-Files ändern.
Wie sieht denn überhaupt eure Deployment-Strategie aus?
 
Anzeige

Neue Themen


Oben