In jedem großen Unternehmen, so auch bei der X5 Retail Group, steigt mit der Entwicklung die Anzahl der Projekte, die eine Benutzeranmeldung erfordern. Im Laufe der Zeit ist ein nahtloser Übergang der Benutzer von einer Anwendung zur anderen erforderlich, was die Notwendigkeit eines zentralen Single-Sign-On (SSO) Servers mit sich bringt. Doch was ist zu tun, wenn bereits Identitätsanbieter wie AD oder andere, die nicht über zusätzliche Attribute verfügen, in verschiedenen Projekten eingesetzt werden? Hier kommen Identitätsbroker ins Spiel. Die funktionalsten Vertreter dieser Klasse sind Systeme wie Keycloak, Gravitee Access Management und andere. Die Nutzungsszenarien können sehr unterschiedlich sein: maschinelles Interagieren, Benutzerbeteiligung usw. Die Lösung sollte eine flexible und skalierbare Funktionalität unterstützen, die in der Lage ist, alle Anforderungen in einem System zu vereinen, und in unserem Unternehmen ist derzeit dieser Identitätsbroker – Keycloak.

Keycloak ist ein Open-Source-Produkt, das für die Identitäts- und Zugriffsverwaltung entwickelt wurde und von RedHat unterstützt wird. Es bildet die Grundlage für Produkte des Unternehmens, die SSO – RH-SSO – verwenden.
Wichtige Konzepte
Bevor Sie sich mit den Lösungen und Ansätzen auseinandersetzen, sollten Sie die Begriffe und den Ablauf der Prozesse klären:

Identifikation – dies ist das Verfahren zur Identifikation einer Person anhand ihrer Kennung (einfacher gesagt, es handelt sich um die Bestimmung des Namens, Benutzernamens oder der Nummer).
Authentifizierung – dies ist der Vorgang zur Überprüfung der Echtheit (ein Benutzer wird durch ein Passwort überprüft, eine E-Mail wird durch eine elektronische Signatur validiert usw.)
Autorisierung – dies ist die Gewährung des Zugriffs auf eine Ressource (z. B. auf eine E-Mail).
Identitätsbroker Keycloak
Keycloak ist eine Lösung zur Verwaltung von Identität und Zugriff, die als Open Source entwickelt wurde und für Systeme geeignet ist, die Muster der Microservices-Architektur verwenden.
Keycloak bietet Funktionen wie Single Sign-On (SSO), Identitätsvermittlung und sozialen Login, Benutzermanagement, Client-Adapter, die Administrationskonsole und die Kontoverwaltungskonsole.
Die grundlegenden Funktionen, die von Keycloak unterstützt werden, sind:
- Single Sign-On und Single Sign-Out für Webanwendungen.
- Unterstützung für OpenID/OAuth 2.0/SAML.
- Identitätsvermittlung – Authentifizierung über externe OpenID Connect oder SAML Identitätsanbieter.
- Soziale Login – Unterstützung von Google, GitHub, Facebook, Twitter zur Benutzeridentifizierung.
- Benutzermanagement – Synchronisierung von Benutzern aus LDAP- und Active Directory-Servern sowie anderen Identitätsanbietern.
- Kerberos-Brücke – Verwendung eines Kerberos-Servers zur automatischen Authentifizierung von Benutzern.
- Administrationskonsole – für die zentrale Verwaltung von Einstellungen und Konfigurationen über das Web.
- Kontoverwaltungs-Konsole – für die selbstständige Verwaltung von Benutzerprofilen.
- Anpassung der Lösung basierend auf dem Firmen-CI.
- 2FA-Authentifizierung – Unterstützung für TOTP/HOTP mit Google Authenticator oder FreeOTP.
- Login-Flows – Selbstregistrierung von Benutzern, Wiederherstellung und Zurücksetzung von Passwörtern und mehr.
- Session Management – Administratoren können Benutzer-Sessions zentral verwalten.
- Token Mappers – Zuordnung von Benutzerattributen, Rollen und anderen erforderlichen Attributen in Tokens.
- Flexible Verwaltung von Richtlinien über Realm, Anwendungen und Benutzer.
- CORS-Unterstützung – Clientadapter verfügen über integrierte CORS-Unterstützung.
- Service Provider Interfaces (SPI) – Eine Vielzahl von SPI, die es ermöglichen, verschiedene Aspekte des Serverbetriebs zu konfigurieren: Authentifizierungsflüsse, Identitätsanbieter, Protokollzuordnungen und vieles mehr.
- Clientadapter für JavaScript-Anwendungen, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Spring.
- Unterstützung für die Interaktion mit verschiedenen Anwendungen, die die OpenID Connect Relying Party Library oder die SAML 2.0 Service Provider Library unterstützen.
- Erweiterbarkeit durch Nutzung von Plugins.
Für CI/CD-Prozesse sowie die Automatisierung von Verwaltungsprozessen in Keycloak kann das REST API/JAVA API verwendet werden. Die Dokumentation ist elektronisch verfügbar:
REST API
JAVA API
Enterprise-Identitätsanbieter (On-Premise)
Möglichkeit zur Authentifizierung von Benutzern über User Federation-Dienste.

Es kann auch eine durchgehende Authentifizierung verwendet werden — wenn Benutzer sich an Arbeitsplätzen mit Kerberos (LDAP oder AD) authentifizieren, können sie sich automatisch bei Keycloak anmelden, ohne ihr Benutzername und Passwort erneut eingeben zu müssen.
Für die Authentifizierung und anschließende Autorisierung von Benutzern ist die Verwendung einer relationalen Datenbank von Vorteil, da sie sich besonders für Entwicklungsumgebungen eignet und keine umfangreichen Konfigurationen und Integrationen in den frühen Projektphasen erfordert. Standardmäßig verwendet Keycloak eine integrierte Datenbank zur Speicherung von Einstellungen und Benutzerdaten.
Die Liste der unterstützten Datenbanken ist umfangreich und umfasst: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle und weitere. Die am besten getesteten sind derzeit Oracle 12C Release1 RAC und der Galera 3.12-Cluster für MariaDB 10.1.19.
Identitätsanbieter — Social Login
Die Nutzung von Logging über soziale Netzwerke ist möglich. Zur Aktivierung dieser Funktion wird das Admin-Panel von Keycloak verwendet. Es sind keine Änderungen am Anwendungscode erforderlich; diese Funktionalität ist "out of the box" verfügbar und kann in jeder Phase des Projekts aktiviert werden.

Für die Benutzerautorisierung können OpenID/SAML Identity Provider verwendet werden.
Typische Autorisierungsszenarien mit OAuth2 in Keycloak
Authorization Code Flow — wird bei serverseitigen Anwendungen verwendet. Dies ist einer der am weitesten verbreiteten Autorisierungsansätze, da er gut für serverseitige Anwendungen geeignet ist, bei denen der Anwendungscode und die Kundendaten für Dritte nicht zugänglich sind. Der Prozess basiert in diesem Fall auf einer Weiterleitung (Redirection). Die Anwendung muss in der Lage sein, mit einem Benutzeragenten, wie einem Webbrowser, zu interagieren, um Autorisierungscodes über den Benutzeragenten zu empfangen.
Implicit Flow — wird von mobilen oder Webanwendungen verwendet (Anwendungen, die auf den Geräten der Benutzer laufen).
Der implizite Autorisierungsflow wird von mobilen und Webanwendungen verwendet, bei denen die Vertraulichkeit des Nutzers nicht garantiert werden kann. Dieser Flow nutzt ebenfalls eine Umleitung des User Agents, wobei das Zugriffstoken an den User Agent übermittelt wird, um es später in der Anwendung zu verwenden. Dadurch wird das Token für den Nutzer und andere Anwendungen auf dessen Gerät verfügbar. Bei diesem Typ der Autorisierung findet keine Authentifizierung der Anwendung statt, und der gesamte Prozess beruht auf der Umleitungs-URL, die zuvor im Dienst registriert wurde.
Der implizite Flow unterstützt keine Zugriffstoken-Refresh-Tokens.
Client-Credentials-Grant-Flow — werden verwendet, wenn Anwendungen auf eine API zugreifen. Diese Art der Autorisierungsberechtigung wird in der Regel für "Server-zu-Server"-Interaktionen eingesetzt, die im Hintergrund ohne sofortige Benutzerinteraktion durchgeführt werden müssen. Der Fluss der Client-Anmeldeinformationen ermöglicht es einem Webdienst (vertraulichen Client), seine eigenen Anmeldeinformationen anstelle der Benutzeridentität zur Authentifizierung beim Aufruf eines anderen Webdienstes zu verwenden. Um ein höheres Sicherheitsniveau zu gewährleisten, kann der aufrufende Dienst ein Zertifikat (anstelle eines gemeinsamen Geheimnisses) als Anmeldeinformationen verwenden.
Die OAuth2-Spezifikation ist beschrieben in
JWT-Token und seine Vorteile
JWT (JSON Web Token) ist ein offener Standard (), der einen kompakten und autonomen Weg zur sicheren Übertragung von Informationen zwischen Parteien in Form eines JSON-Objekts definiert.
Laut den Standards besteht ein Token aus drei Teilen im Base-64-Format, die durch Punkte getrennt sind. Der erste Teil wird als Header bezeichnet und enthält den Typ des Tokens sowie den Namen des Hash-Algorithmus zur Erzeugung der digitalen Signatur. Der zweite Teil speichert die grundlegenden Informationen (Benutzer, Attribute usw.). Der dritte Teil ist die digitale Signatur.
..
Speichern Sie ein Token niemals in Ihrer Datenbank. Denn ein gültiges Token ist gleichbedeutend mit einem Passwort; ein Token zu speichern ist dasselbe, wie ein Passwort im Klartext zu speichern.
Access-Token ist ein Token, das seinem Inhaber Zugriff auf geschützte Ressourcen des Servers gewährt. In der Regel hat es eine kurze Lebensdauer und kann zusätzliche Informationen enthalten, wie die IP-Adresse der anfordernden Partei.
Refresh-Token ist ein Token, das es Clients ermöglicht, neue Access-Token nach Ablauf ihrer Lebensdauer anzufordern. Diese Tokens werden in der Regel für einen längeren Zeitraum ausgestellt.
Die Hauptvorteile der Verwendung in einer Mikroservice-Architektur:
- Die Möglichkeit, auf verschiedene Anwendungen und Dienstleistungen durch einmalige Authentifizierung zuzugreifen.
- Fehlen bestimmte erforderliche Attribute im Benutzerprofil, können Daten hinzugefügt werden, die automatisch und „on-the-fly“ in die Payload integriert werden können.
- Es besteht keine Notwendigkeit, Informationen über aktive Sitzungen zu speichern; die serielle Anwendung muss nur die Signatur überprüfen.
- Flexibleres Zugriffsmanagement durch zusätzliche Attribute in der Payload.
- Die Verwendung der Token-Signatur für den Header und die Payload erhöht die Sicherheit der gesamten Lösung.
JWT-Token – Komponenten
Header – standardmäßig enthält der Header nur den Token-Typ und den Algorithmus, der zur Verschlüsselung verwendet wird.
Der Token-Typ wird im Schlüssel „typ“ gespeichert. Der Schlüssel „typ“ wird in JWT ignoriert. Wenn der Schlüssel „typ“ vorhanden ist, muss sein Wert JWT sein, um anzugeben, dass dieses Objekt ein JSON Web Token ist.
Der zweite Schlüssel „alg“ definiert den Algorithmus, der zur Verschlüsselung des Tokens verwendet wird. Standardmäßig sollte er auf HS256 gesetzt sein. Der Header wird in base64 kodiert.
{ "alg": "HS256", "typ": "JWT"}
Payload (Inhalt) — im Payload werden alle Informationen gespeichert, die überprüft werden müssen. Jeder Schlüssel im Payload wird als „Anspruch“ bezeichnet. Zum Beispiel kann man sich nur auf Einladung (geschlossene Promotion) in die Anwendung einloggen. Wenn wir jemanden einladen möchten, senden wir ihm eine Einladung per E-Mail. Es ist wichtig, dass die E-Mail-Adresse der Person gehört, die die Einladung annimmt, deshalb werden wir diese Adresse im Payload einschließen und im Schlüssel „e-mail“ speichern.
{ "email": "example@x5.de" }
Die Schlüssel im Payload können beliebig sein. Es gibt jedoch einige reservierte Schlüssel:
- iss (Issuer) — bestimmt die Anwendung, aus der das Token gesendet wird.
- sub (Subject) — bestimmt das Thema des Tokens.
- aud (Audience) – ein Array von schreibsensitiven Zeichenfolgen oder URIs, das die Liste der Empfänger dieses Tokens darstellt. Wenn die empfangende Partei ein JWT mit diesem Schlüssel erhält, muss sie überprüfen, ob sie in den Empfängern enthalten ist – andernfalls ignoriert sie das Token.
- exp (Ablaufzeit) — gibt an, wann das Token abläuft. Der JWT-Standard verlangt, dass alle Implementierungen Tokens mit abgelaufener Gültigkeit ablehnen. Der Exp-Schlüssel sollte ein Zeitstempel im Unix-Format sein.
- nbf (Nicht vor) — dies ist die Zeit im Unix-Format, die den Moment angibt, ab dem das Token gültig wird.
- iat (Ausgestellt am) — dieser Schlüssel stellt die Zeit dar, zu der das Token ausgestellt wurde und kann zur Bestimmung des Alters des JWT verwendet werden. Der iat-Schlüssel sollte ein Zeitstempel im Unix-Format sein.
- Jti (JWT-ID) — eine Zeichenfolge, die eine eindeutige Kennung für dieses Token unter Berücksichtigung der Groß- und Kleinschreibung definiert.
Es ist wichtig zu verstehen, dass die Nutzlast nicht in verschlüsselter Form übertragen wird (obwohl Tokens verschachtelt sein können, wodurch die Übertragung verschlüsselter Daten möglich ist). Daher dürfen keine vertraulichen Informationen darin gespeichert werden. Wie der Header wird die Nutzlast in base64 codiert.
Signatur — sobald wir Header und Nutzlast haben, können wir die Signatur berechnen.
Die in base64 kodierten Teile sind der Header und der Payload, die durch einen Punkt zu einer Zeichenkette verbunden werden. Anschließend wird diese Zeichenkette zusammen mit dem geheimen Schlüssel in den Verschlüsselungsalgorithmus eingegeben, der im Header angegeben ist (Schlüssel „alg“). Der Schlüssel kann jede beliebige Zeichenkette sein. Längere Zeichenketten sind bevorzugt, da sie mehr Zeit für die Entschlüsselung erfordern.
{"alg":"RSA1_5","payload":"A128CBC-HS256"}
Aufbau einer ausfallsicheren Keycloak-Cluster-Architektur
Bei der Nutzung eines einzigen Clusters für alle Projekte ergeben sich höhere Anforderungen an die SSO-Lösung. Wenn die Anzahl der Projekte gering ist, sind diese Anforderungen für alle Projekte nicht so spürbar, jedoch steigen sie mit zunehmender Nutzerzahl und Integrationen, wodurch die Anforderungen an Verfügbarkeit und Leistung wachsen.
Die Erhöhung der Ausfallrisiken eines zentralen SSO erhöht die Anforderungen an die Architektur der Lösung und die verwendeten Methoden zur Redundanz der Komponenten und führt zu einem sehr strengen SLA. Daher verfügen Projekte in der Regel während der Entwicklungsphase oder in den frühen Phasen der Implementierung über eine eigene nicht fehlertolerante Infrastruktur. Mit fortschreitender Entwicklung ist es notwendig, vorab Entwicklungsmöglichkeiten und Skalierung einzuplanen. Es ist am flexibelsten, einen fehlertoleranten Cluster unter Verwendung von Container-Virtualisierung oder einem hybriden Ansatz aufzubauen.
Für den Betrieb von Active/Active- und Active/Passive-Clustern ist es erforderlich, die Konsistenz der Daten in der relationalen Datenbank sicherzustellen – beide Datenbankknoten müssen synchron zwischen verschiedenen geo-verteilten Rechenzentren repliziert werden.
Das einfachste Beispiel für eine fehlertolerante Installation.

Welche Vorteile bietet die Verwendung eines einheitlichen Clusters:
- Hohe Verfügbarkeit und Leistung.
- Unterstützung für die Betriebsarten: Active/Active, Active/Passive.
- Möglichkeiten für dynamische Skalierung – bei Verwendung von Container-Virtualisierung.
- Zentralisierte Verwaltung und Überwachung.
- Ein einheitlicher Ansatz zur Identifikation/Authentifizierung/Autorisierung von Nutzern in Projekten.
- Transparente Interaktion zwischen verschiedenen Projekten ohne Nutzerbeteiligung.
- Möglichkeit zur Wiederverwendung des JWT-Tokens in verschiedenen Projekten.
- Einheitlicher Vertrauenspunkt.
- Schnellerer Projektstart mit Mikrodiensten/Container-Virtualisierung (es sind keine zusätzlichen Komponenten erforderlich).
- Kommerzielle Unterstützung durch den Anbieter ist verfügbar.
Worauf Sie bei der Planung eines Clusters achten sollten
Datenbankmanagementsystem
Keycloak verwendet ein Datenbankmanagementsystem zur Speicherung von: realms, clients, users usw.
Eine Vielzahl von Datenbankmanagementsystemen wird unterstützt: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak wird mit einer eigenen eingebauten relationalen Datenbank geliefert. Die Nutzung wird für wenig belastete Umgebungen empfohlen – wie etwa Entwicklungsumgebungen.
Für den Betrieb in einem Active/Active- und Active/Passive-Cluster muss die Datenkonsistenz in der relationalen Datenbank gewährleistet sein, und beide Knoten des Datenbankclusters werden synchron zwischen den Rechenzentren repliziert.
Verteiltes Cache (Infinispan)
Für das ordnungsgemäße Funktionieren des Clusters ist eine zusätzliche Synchronisation der folgenden Cache-Typen unter Verwendung von JBoss Data Grid erforderlich:
Authentifizierungssitzungen – werden verwendet, um Daten während der Authentifizierung eines bestimmten Benutzers zu speichern. Anfragen aus diesem Cache beinhalten in der Regel nur den Browser und den Keycloak-Server, nicht jedoch die Anwendung.
Aktionstoken – werden in Szenarien verwendet, in denen der Benutzer eine Aktion asynchron bestätigen muss (z. B. per E-Mail). Während des Prozesses 'Passwort vergessen' wird der Cache actionTokens in Infinispan verwendet, um Metadaten über die bereits verwendeten Aktionsmarker zu verfolgen, damit sie nicht erneut verwendet werden können.
Caching und Invalidierung von persistenten Daten – wird verwendet, um persistente Daten zu cachen, um unnötige Datenbankanfragen zu vermeiden. Wenn ein Keycloak-Server Daten aktualisiert, müssen alle anderen Keycloak-Server in allen Rechenzentren darüber informiert werden.
Arbeit – wird nur verwendet, um Ungültigkeitsmeldungen zwischen den Knoten des Clusters und den Rechenzentren zu senden.
Benutzersitzungen — werden genutzt, um Daten über Benutzersitzungen zu speichern, die während der Browsersitzung des Benutzers gültig sind. Der Cache muss HTTP-Anfragen von Endbenutzern und Anwendungen verarbeiten.
Brute-Force-Schutz — wird eingesetzt, um Daten über fehlgeschlagene Anmeldeversuche zu verfolgen.
Lastenausgleich
Der Lastenverteiler ist der einzige Einstiegspunkt für Keycloak und muss sticky sessions unterstützen.
Anwendungsserver
Werden zur Kontrolle der Interaktion zwischen Komponenten verwendet und können mit vorhandenen Automatisierungs- und dynamischen Skalierungstools virtualisiert oder containerisiert werden. Die häufigsten Bereitstellungsszenarien sind OpenShift, Kubernetes, Rancher.
Hier endet der erste Teil – der theoretische. In den nächsten Artikeln werden Beispiele für Integrationen mit verschiedenen Identitätsanbietern sowie Konfigurationen behandelt.
Quelle: habr.com
