Sign Up / Login ScreenAls IT-Berater sind wir immer wieder mit Integrationsprojekten befasst. Vor allem im Rahmen von Modernisierungs- oder Neuimplementierungsprojekten kommt man dabei irgendwann immer an den Punkt eine Authentifizierungslösung zu integrieren. Oftmals ist in solchen Projekten eine der Randbedingungen, die vorhandene Identitätsmanagementlösung (IAM) zu nutzen.

Aber wie sinnvoll ist eine tiefe Integration solcher Lösungen im Zeitalter von verteilten, dezentralen Systemen und Microservices noch?

Gar nicht – zumindest nicht unter der Prämisse, dass die Entscheidung zum Einsatz verteilter (Microservice-) Architekturen oftmals auf Argumenten der Skalierung beruht.

Das Problem mit der Integration

Um das Problem zu verstehen, betrachten wir zunächst einmal den Fall einer monolithischen Architektur. Das hier traditionell vorherrschende Paradigma zur Identitätskontrolle sieht in der Regel folgendermaßen aus.

Alle Benutzerinformationen sind in einem zentralen Repository (z.B. LDAP, Active Directory, Datenbank etc.) gespeichert. Durch eine direkte Integration einer Sicherheitskomponente in der Anwendung, die wie eine Barriere funktioniert, wird sichergestellt, dass der Benutzer authentifiziert wird. Da alle Komponenten in einem Monolithen gemeinsam deployed sind, teilen sie sich dadurch die Verbindung zum Repository, aber auch den Zustand der Authentifizierung. Alle Komponenten wissen, ob und welcher Benutzer angemeldet ist.

Die Sicherheitskomponente prüft die Anmeldedaten des Benutzers gegen das Repository. Sind die Anmeldedaten korrekt, wird die Identität des Benutzers an die anderen Komponenten weitergereicht und von diesen nicht weiter geprüft. Oftmals geht dies einher mit der Etablierung einer Session zwischen Client und Server. Hierbei handelt es sich um eine Optimierung. Sie dient dazu, dass nicht bei jeder Anfrage an den Server die Identität des Benutzers ermittelt und erneut sichergestellt werden muss. Diese ist stattdessen mit der etablierten Session verheiratet.

Übertragen wir diese Art der Integration in eine verteilte Microservice-Architektur, ergibt sich vor dem Hintergrund der Skalierbarkeit vor allem ein Problem. Jede einzelne Komponente ist nun quasi in einem eigenständigen Microservice deployed. Das hat zur Folge, dass auch jeder Microservice seine eigene Sicherheitskomponente bzw. Barriere benötigt. Jeder Service hat somit auch eine Verbindung an das Repository und muss bei einer Anfrage die Anmeldedaten des Benutzers prüfen.

Das ist nicht nur in Hinblick auf die Systemabhängigkeiten ein Albtraum. Jeder Microservice hat jetzt nicht nur eine Abhängigkeit auf das zentrale Repository; sollten sich einzelne Microservices untereinander aufrufen, ist dieses Vorgehen zusätzlich hochgradig ineffizient. Eine solche Aufrufkette endet zwangsweise in mehreren Anfragen an das Repository. Außerdem kann die Nutzung von Sessions nur sinnvoll aufrechterhalten werden, wenn sich alle Microservices die Sessioninformationen teilen. Eine weitere Kopplung zwischen allen Microservices.

Integrative Authentifizierung im verteilten System

OAuth2 als Basis für eine Lösung

Eine weitaus effizientere Lösung bieten Mechanismen wie OAuth2. OAuth2 unterscheidet im Wesentlichen vier Parteien, die miteinander kommunizieren. Zum einen ist dies ein s.g. Resource Owner. Das ist der Benutzer, der unsere Microservices nutzen möchte. Dieser bedient sich eines Clients. Das kann z.B. eine mobile App oder ein Single Page Application sein. Die eigentliche Authentifizierung erfolgt durch einen Authorization Server. Letztlich werden die Microservices als Resource Server bezeichnet.

OAuth2 Abstract Protocol Flow

Der Ablauf, um einem Benutzer Zugriff auf einen Microservice zu gewähren, ist etwas komplex, stellt sich aber in etwa wie folgt dar:
Der Benutzer fragt über seinen Client den Zugriff auf den Resource Server beim Authorization Server an. Der Authorization Server authentifiziert den Benutzer anhand seiner Anmeldedaten wie z.B. Benutzername und Passwort. Sind diese korrekt, stellt der Authorization Server ein s.g. Access Token an den Client aus. Dieser kann das Access Token nutzen, um den Ressource Server aufzurufen.

Dabei sendet der Client bei jedem Aufruf des Ressource Servers das Access Token mit. Der Ressource Server kann den Zugriff auf die angefragten Daten oder Funktionalitäten freigeben, nachdem er das Access Token validiert und dessen Gültigkeit festgestellt hat.

Dazu hat der Resource Server zwei Möglichkeiten:

Zum einen kann er mit dem Token den Authorization Server anfragen, der für ihn das Access Token verifiziert. Der Authorization Server kann dann mit relevanten Informationen antworten, wie z.B. dem Benutzernamen, dem Ablaufzeitpunkt des Tokens und mehr oder minder beliebigen weiteren Informationen.
Problematisch ist hierbei in unserem Szenario jedoch, dass wieder eine Integration der Resource Server (unserer Microservices) mit einem zentralen System (dem Authorization Server) notwendig wird. In diesem Falle hätten wir nur das Benutzer-Repository gegen den Authorization Server ausgetauscht. Im Sinne der Skalierbarkeit hätten wir somit nichts gewonnen.

Föderative Authentifizierung

Allerdings besteht für den Resource Server auch noch eine andere Möglichkeit das Token zu verifizieren, die diese Integration nicht notwendig macht. Die Lösung liegt hier in der Kryptographie oder genauer in einem Public-Key-Verschlüsselungsverfahren oder zumindest einer entsprechenden Signatur.

Der Authorization Server kann die vom Resource Server benötigten Informationen einfach in das Access Token codieren. Das Token kann er dann mit einem privaten Schlüssel verschlüsseln oder zumindest signieren. Der Resource Server verfügt über den entsprechenden öffentlichen Schlüssel und kann somit die Echtheit des Tokens prüfen. Diese Art der Integration macht keine direkte Kommunikation zwischen Resource Sever und Authorization Server notwendig.

Man spricht daher hier auch von einem föderativen Authentifizierungsverfahren. Das Verfahren basiert ausschließlich auf Vertrauen. Offensichtlich wird auf Basis des Public-Key-Verschlüsselungsverfahrens eine Vertrauensstellung zwischen Authorization Server, Ressource Server und Client etabliert.

Als Standard hat sich hierzu mit OpenId Connect eine Erweiterung des OAuth2-Protokolls etabliert. Während Access Tokens im Rahmen von OAuth2 oftmals von Clients nicht interpretierbar sind (z.B. zufällig generierte GUIDs), standardisiert OpenId Connect wie Identitätsinformationen in das Token codiert werden können. Hierzu setzt es auf einen weiteren Standard auf, nämlich JSON Web Tokens (JWTs). Diese erlauben es mittels JSON Objekten s.g. Claims zwischen Parteien auszutauschen. Es ist somit möglich weitere Informationen wie Gruppenzugehörigkeit, Rollen oder ähnliches in die Tokens zu codieren.

Zentrale Integration

Wie hilft uns das bei unserem ursprünglichen Problem – der Integration einer vorhandenen Authentifizierungslösung?

Indem wir die Integration auf einen einzelnen Punkt in der Gesamtsystemumgebung beschränken können. Das vorhandene System muss nun ausschließlich mit dem Authorization Server integriert werden. In einem föderativen Ansatz authentifiziert nur dieser den Benutzer.

Unsere Microservices müssen lediglich die Access Tokens verifizieren. Sie erhalten alle notwendigen Informationen (insbesondere die Identität des Benutzers) durch deren Übermittlung bei jeder Anfrage direkt mitgeliefert. Müssen einzelne Microservices andere Microservices aufrufen, können Access Tokens außerdem für eine Delegation genutzt werden.

Föderative Authentifizierung mit zentraler Integration eines User Repositories

Föderation statt Integration

Wie wir gesehen haben, bieten föderative Authentifizierungsmechanismen große Vorteile in Bezug auf die Skalierbarkeit verteilter Systemarchitekturen wie Microservices.

Die Kopplung aller Teilsysteme an ein zentrales Repository wird massiv verringert, so dass sich wesentlich weniger (direkte) Abhängigkeiten zwischen den Systemen ergeben. Auch die Kopplung von Microservices durch Aufrufe untereinander kann so effizienter gestaltet werden. Die Notwendigkeit der Verifizierung der Benutzeridentität gegen ein zentrales System entfällt.

Ich empfehle daher dringen zu prüfen, ob ein föderativer Ansatz bei der Anbindung vorhandener IAM-Lösungen eine Option darstellt. Gerne unterstützen unsere Architekturberater in dieser und ähnlichen Fragestellungen.