Über unsMediaKontaktImpressum
Florian Bader & Dustin Baron 20. September 2022

Self-made Identity: Zentrale Authentifizierung in der Cloud

Die eigene Domäne und alle verknüpften Systeme im Hinblick auf Digitalisierung in die Cloud zu bringen ist ein riesiger Schritt für jedes Unternehmen. Dabei ist es oft ein notwendiger Schritt, eine zentrale Stelle zur Authentifizierung in der Cloud bereitzustellen. Wann ergibt das Sinn und was sollte dabei beachtet werden?

Im Zuge der Digitalisierung ist ein entscheidender Punkt, seine verschiedenen Systeme und Prozesse durch eine einheitliche Authentifizierung und Autorisierung abzusichern.

Problemstellung

Viele Anwendungen haben dazu ihr eigenes System, erlauben aber auch die Integration anderer Authentifizierungsprotokolle wie LDAP oder OpenID Connect (OIDC). Um die Benutzerakzeptanz zu erhöhen sowie den Verwaltungsaufwand zu reduzieren, bietet es sich an, auf eine zentrale Identity-Lösung zu setzen. Das vereinfacht nicht nur die Anmeldung, sondern erlaubt auch ein einheitliches Bild nach außen.

Dies soll anhand der fiktiven Beispielfirma Werkzeughersteller GmbH verdeutlicht werden. Sie fertigt Werkzeuge und verkauft diese direkt im B2B-Umfeld. Da die Werkzeughersteller GmbH Premium-Werkzeuge verkauft, können diese nur direkt von anderen Firmen über eine designierte Person gekauft werden. Dieser Bestellprozess und die Integration in das ERP- und CRM-System soll digitalisiert werden. Damit Kunden sich selbst anmelden und ihre Werkzeuge in Zukunft im Internet bestellen können, bedarf es einer einheitlichen Authentifizierung. Um die Corporate Identity zu stärken, soll ein eigener Identity Provider mit eigener Werkzeughersteller-ID erstellt werden. Diese Werkzeughersteller-ID kann dann für alle Arten von Anwendungen verwendet und ebenfalls in die Bestandssysteme wie ERP und CRM integriert werden.

Doch wie einfach ist es, einen eigenen Identity Provider zu erstellen und ist das ratsam? Welche Möglichkeiten gibt es und wie können Entscheidungen getroffen werden? Im Folgenden soll dies näher betrachtet und analysiert werden.

Zunächst müssen einige wichtige Punkte geklärt werden, um den Grundstein für die finale Lösung zu legen. Eine wichtige Rolle spielt das Verständnis der Kundendomäne sowie ein genaues Bild der Bedürfnisse und Anforderungen der Endkunden sowie der eigenen Mitarbeitenden. Hier muss nicht nur verstanden werden, wie die Endkunden mit der Lösung arbeiten, sondern auch wie die eigenen Mitarbeitenden mit der Lösung arbeiten sollen. Dabei gibt es bestimmt auch schon viele Wünsche von den eigenen Mitarbeitenden und den Endkunden, die beachtet werden sollten. Darüber hinaus müssen Bestandssysteme inklusive möglicher Altlasten analysiert und verstanden werden. Basierend auf diesen gibt es zusätzliche technische Anforderungen, welche die Wahl der besten Lösung einschränken können. Ebenso muss geklärt werden, wer den Identity Provider implementiert, betreibt und wartet. Auch externe Partner, die über den Identity Provider auf Produktdaten zugreifen sollen, gilt es zu berücksichtigen. Diesen muss unter Umständen ein dedizierter Zugang bereitgestellt werden.

Ziel des Vorgehens ist es, eine Identität zu haben, die mehrere Aspekte beinhaltet: In welcher Funktion (Mitarbeitender, Privat- oder Geschäftskunde) möchte die Person zugreifen? Auf welche Dienste hat die Person Zugriff? Welche Berechtigungen hat die Person?

Konzept & Terminologie

Vor der näheren Betrachtung der Identity Provider sollen einige Konzepte und Terminologien geklärt werden [1].

Ein Identity Provider wird dazu verwendet, digitale Identitäten von Benutzern zu verwalten und zu speichern [2]. Die Identität kann dabei unterschiedliche Eigenschaften beinhalten, z. B. Name, Funktion oder Adresse. Die digitale Identität kann mit einem Personalausweis verglichen werden, der zur Legitimierung genutzt wird. Da es sich bei vielen dieser Informationen um personenbezogene Daten handelt, muss damit besonders achtsam umgegangen werden. Daher sollte unbedingt der zuständige Datenschutzbeauftragte involviert werden.

Die Prüfung der digitalen Identität nennt sich Authentifizierung. Die Anwendung kann so identifizieren, um wen es sich handelt. Um zu prüfen, worauf der Benutzer Zugriff hat, wird noch eine Berechtigung benötigt. Dies lässt sich mit einer Zugangskarte vergleichen. Diesen Vorgang nennt man Autorisierung. Die beiden Schritte sollten getrennt betrachtet und nicht miteinander vermischt werden.

Wie eingangs erwähnt, gibt es verschiedene Authentifizierungsprotokolle. In diesem Beitrag sollen vor allem OpenID und OAuth betrachtet werden.

  • OpenID Connect ist ein Authentifizierungsprotokoll, das die Anmeldung von Benutzern bei Webanwendungen abbildet [3]. Dieses erstellt für die Anmeldung einen sogenannten ID-Token. Dies ist ein JSON Web Token (JWT), welcher zusätzliche Informationen als Base64-kodiertes JSON inklusive Signatur zum Überprüfen der Echtheit abbildet. Im Vergleich von oben ist dieser ID-Token der Personalausweis.
  • OAuth ist ein Autorisierungsprotokoll, das die Zugriffskontrolle von Benutzern bei Webanwendungen abbildet [4]. Bei OAuth wird ein Access-Token erstellt, ähnlich dem ID-Token in OpenID. Der Access-Token ist vergleichbar mit der Zugangskarte und berechtigt den Benutzer für den Zugriff auf Ressourcen und Anwendungen.

Die Webanwendungen, bei denen sich ein Benutzer authentifiziert und autorisiert nennen sich Clients (s. Abb. 1). Dadurch kann unterschieden werden, welcher Benutzer welchen Zugriff auf welche Clients hat. Auch können pro Client unterschiedliche Informationen des Benutzers bereitgestellt werden. Das ist besonders mit Blick auf die DSGVO spannend, denn eventuell sollen einer Third-Party-Anwendung nicht alle personenbezogenen Daten der Benutzer zur Verfügung gestellt werden, sondern nur die relevanten Daten.

Vergleich Identity Provider

Um das Rad nicht neu zu erfinden, wollen wir uns anschauen, welche Lösungen für Identity Provider bereits existieren. Da die Prozesse digitalisiert und auch die Anwendungen in der Cloud über das Internet erreichbar sein sollen, fällt die Wahl auf eine Lösung, die in der Cloud erreichbar ist. Wie bei vielen anderen Diensten gibt es im heutigen Cloudzeitalter zwei Wege zum Ziel: Software-as-a-service (SaaS) oder Platform-as-a-service (PaaS).

Eine SaaS-Lösung ist ein Identity Provider, der fertig eingekauft wird und von einem Anbieter gehostet wird. Somit muss nur die Konfiguration, nicht jedoch der Betrieb des Identity Providers, übernommen werden. Dieser Weg ist vor allem dann von Vorteil, wenn nicht ausreichend Personal oder Expertise vorhanden sind. Andererseits bietet die fertige Lösung meist einen fixen Umfang an Features. Anpassungen oder Erweiterungen an die individuelle Domäne sind nur im Rahmen, den das Produkt als Customizing bereitstellt, möglich. Ebenso gibt es normalerweise keinen Zugriff auf den Source-Code, wodurch eine Abhängigkeit von der Lösung entsteht. Zu den verbreitetsten SaaS-Lösungen für Identity Provider zählen Microsoft Azure Active Directory und Okta Auth0. Beide haben wiederum ihre Vor- und Nachteile, die es anhand individueller Bedürfnisse gegeneinander abzuwägen gilt.

Eine PaaS-Lösung ist dagegen ein Identity Provider, der ebenfalls fertig eingekauft wird oder sogar frei als Open Source verfügbar ist. Dieser muss jedoch selbst betrieben und gewartet werden. Einige SaaS-Lösungen gibt es ebenfalls als PaaS-Angebot, sodass die Entscheidung, ob das Hosting selbst oder durch den Anbieter übernommen werden soll, getroffen werden kann. Der große Vorteil bei einer PaaS-Lösung ist die Flexibilität und Freiheit, die Lösung an die eigenen Anforderungen anzupassen.

Im Fall der Werkzeughersteller GmbH fiel die Wahl auf eine PaaS-Lösung, um volle Kontrolle über den Identity Provider, die Daten und auch das Customizing der Lösung zu haben. Es war zu erwarten, dass Erweiterungen am Prozess nötig sein werden, die mit SaaS-Lösungen nur schwierig umsetzbar gewesen wären.

Zu den verbreitetsten selbst betreibbaren Identity Providern gehören Keycloak und Duende Identity Server. Während Keycloak kostenlos verfügbar ist, gibt es den Duende Identity Server nur kostenpflichtig. Die Open-Source-Variante von Identity Server in der Version 4 ist zwar kostenlos, wird aber nur noch bis November 2022 gepflegt. Bezüglich der Funktionalitäten sind beide ähnlich. Je nachdem was die Anforderungen sind, kann die Entscheidung schon stark eingrenzen. Beide unterstützen sowohl Open ID Connect, OAuth 2.0, SAML 2.0 und haben eine LDAP-Integration. SAML und LDAP ist vor allem relevant, wenn eine vorliegende On-Premise-Welt in den neuen Identity Provider integriert werden soll und z. B. Active-Directory-Authentifizierung oder die Integration von Drittsoftware unterstützt werden muss.

Während Keycloak in Java entwickelt wird, basiert der Identity Server auf .NET. Das kann ein ausschlaggebendes Argument sein, je nachdem in welchem Technologie-Stack mehr Expertise und Personal vorhanden ist. Sowohl bei der Dokumentation als auch bei der Einstiegshürde glänzen beide und ermöglichen es schnell, die Lösung aufzusetzen und zu konfigurieren. Auch das Customizing ist bei beiden ähnlich einfach durchführbar.

Bei der Werkzeughersteller GmbH wurde der Duende Identity Server ausgewählt, da mehr Expertise in .NET vorhanden war. Wichtig ist, dass die Entscheidung nicht aus Kostengründen getroffen wird. Nur weil Keycloak im Vergleich zu Duende Identity Server kostenlos ist, sollte die Entscheidung nicht automatisch auf die kostenlose Variante fallen. Besonders mit Blick auf Security sollte nicht an der falschen Stelle gespart werden.

Einblick in Duende Identity Server

Der Duende Identity Server ist ein OpenID-Connect- und OAuth-2.0-Framework für ASP.NET Core und ermöglicht einen schnellen und einfachen Einstieg für eine solide Identity-Provider-Lösung. Dabei bietet er im Standard eine Authentifizierung als Service, Single Sign On, Access Control für API und einige andere Funktionalitäten [5].

Hervorzuheben ist vor allem die Möglichkeit zur Erweiterung des Duende Identity Servers, da direkt in die Abläufe des Identity Servers eingegriffen und ohne großen Aufwand per Dependency Injection eigene Implementierungen eingebunden werden können.

Im Folgenden wird erläutert, wie eine Lösung mit dem Identity Server aufgesetzt werden kann und wie einfach ein Eingriff in den Anmeldevorgang des Authentication Flow sein kann.

Fundament – Infrastruktur in Azure

Zu Beginn braucht der Identity Server ein solides Fundament, sei es via Azure, AWS oder einer anderen Cloudlösung. Dabei sind im Beispiel (s. Abb. 2) folgende Ressourcen in Azure teilweise unabdingbar:

  • Azure Web Application – Zum eigentlichen Bereitstellen der Identity-Server-Anwendung und als Schnittstelle unseres Identity Providers.
  • Azure Application Insights – Um gezieltes Logging zu ermöglichen und ein einfaches Tooling zur Fehleranalyse bereitzustellen.
  • Azure SQL Database – Die zugehörige Anwendungsdatenbank des Identity Server, welche die Informationen zu den Clients, API-Ressourcen, Identitäten der Nutzer (z. B. mit ASP.NET Identity[6]) und Zugriffstoken speichert.
  • Azure Key Vault – Zum Speichern von sensiblen Daten wie z. B. dem Zertifikat des Identity Servers und der Datenbankzugriffsdaten für die dazugehörige Anwendung.

Es sollte z. B. via Managed System Identity sichergestellt werden, dass die Azure-Webanwendung Zugriff auf die Azure SQL Database und den Azure Key Vault hat, damit der Identity Server die relevanten Informationen lesen und schreiben kann [7]. Ebenso, dass die Verbindungszeichenfolge für die Datenbank im Key Vault hinterlegt ist, welcher dann schon in der Azure-Webanwendung als Default Connection über den Key Vault konsumiert wird [8].

Zum Testen der Lösung braucht es außerdem einen Client, welcher auf die Schnittstelle des Identity Providers zugreift. Dazu kann einfach eine weitere Azure-Webanwendung dienen, welche im späteren Verlauf mit Easy Auth[9] mit dem Identity Server verknüpft wird, um den Zugriff auf die Anwendung einzuschränken und den Identity Provider zu verifizieren.

Grundgerüst – Mit Vorlage zum Ziel

Glücklicherweise stellt der Duende Identity Server Vorlagen für einen schnellen Einstieg zur Verfügung. Die Vorlagen reichen vom Grundgerüst bis zu erweiterten Anwendungsszenarien. Ob zum Beispiel mit oder ohne grafische Oberfläche, Datenbankanbindung via Entity Framework Core oder einfach einen Minimaleinstieg [10].

Es ist vorher nur notwendig, folgende Schritte lokal in einem gewünschten Verzeichnis auszuführen.

Listing 1: Erstellung Identity Server Solution

# Installiert Template 
dotnet new -i Duende.Identity Server.Templates 
 
# Erstellt ein Projekt mit der Entity Framework Core Vorlage im aktuellen Verzeichnis
dotnet new is4ef

Die Abfrage, ob die Datenbank initial befüllt werden soll, wird zunächst abgelehnt, denn noch fehlen einige kleinere Anpassungen, um die Implementierung mit der Datenbank in Azure zu verknüpfen. 

Dabei lässt sich die Lösung, welche mit der Vorlage erzeugt wurde, alternativ testweise direkt starten und im erzeugten Verzeichnis können in der Config.cs die Ressourcen und im Verzeichnis Pages in der TestBenutzer.cs die Benutzerdaten für die ersten Schritte verwaltet werden. Da der Identity Server kein vollumfängliches Benutzer-Management zur Verfügung stellt, sollte dies für die produktive Nutzung umgestellt werden – eine Möglichkeit wäre z. B. ASP.NET Identity[6].

Anbindung an die Datenbank und der erste Client

Per Default hat das Template eine Anbindung an Entity Framework Core via SQLite. Da der Identity Server aber an die Datenbank in Azure gebunden werden soll, sollten in den nächsten Schritten die Pakete von SQLite durch die des SqlServers für Entity Framework Core ersetzt werden. Zusätzlich muss dann noch von UseSqlite auf UseSqlServer in der HostingExtensions.cs umgestellt werden (s. Listing 2).

Listing 2: Datenbankverbindung nach SQLite

# Ersetzen der Methoden von SQLite 
 options.ConfigureDbContext = b => b.UseSqlite(connectionString, dbOpts => dbOpts.MigrationsAssembly(typeof(Program).Assembly.FullName));

# durch  die Methoden von SQLServer
options.ConfigureDbContext = b => b.UseSqlServer(connectionString, dbOpts => dbOpts.MigrationsAssembly(typeof(Program).Assembly.FullName));

Da die existierenden Migrationen auf SQLite gemünzt sind, wird der Inhalt des Migrations-Verzeichnisses gelöscht und die Migrationen für PersistedGrantDbContext und ConfigurationDbContext neu erstellt (s. Listing 3).

Listing 3: Datenbankmigration mit Entity Framework Core

# Installieren des Toolings für Entity Framework Core
dotnet tool install --global dotnet-ef

# Erstellen der Migrationen
dotnet ef migrations add InitialCreate --context PersistedGrantDbContext
dotnet ef migrations add InitialCreate --context ConfigurationDbContext

Anschließend kann in der appsettings.json die DefaultConnection auf die Azure SQL Database gesetzt und dotnet run/seed im Verzeichnis ausgeführt werden, um die Migration der Datenbank durchzuführen und nachträglich alle konfigurierten Werte aus der Config.cs in die Datenbank zu übertragen.

In diesem Fall werden nur ein Client und bestimmte Scopes des OpenID Connect 1.0 Standards[11] benötigt, um die zweite Azure-Web-Applikation via Easy Auth[9] und den Identity Provider abzusichern.

Listing 4: Clientkonfiguration im Identity Server

public static IEnumerable<IdentityResource> IdentityResources =>
  new IdentityResource[] {
      new IdentityResources.OpenId(),
      new IdentityResources.Profile(),
      new IdentityResources.Email()
  };
 
public static IEnumerable<Client> Clients =>
   new Client[] {
      new Client {
        ClientId = "selfmadeidentityclient",
        ClientSecrets = { new Secret("XXXXXXXXXXXXXXX".Sha256()) },
        AllowedGrantTypes = GrantTypes.Code,
        RedirectUris = { " https://xxx.net/.auth/login/selfmadeidentity/callback" },
        RequirePkce = false,
        AllowOfflineAccess = true,
        AllowedScopes = { "openid", "profile", "email" }
      }
   };

Die Redirect-URL erhält man dabei, indem mit Easy Auth die Webanwendung konfiguriert wird. Dazu wird im Azure-Portal in den Einstellungen Authentifizierung der Webanwendung ein neuer OpenID- Connect-Anbieter hinzugefügt (s. Abb. 3). Die Redirect-URL des Clients entspricht dann <app-url>/.auth/login/<provider-name>/callback (also für das Beispiel: https://selfmadeidentityclient.azureweb sites.net/.auth/login/selfmadeidentity/callback). Und schon wird man beim Zugriff auf den Client zum Identity Server weitergeleitet, wo man sich mittels der Nutzerdaten Zugriff verschaffen kann.

Customization im Duende Identity Server

Abschließend wird nochmal das Thema Customization im Duende Identity Server in der Praxis betrachtet, welches unter anderem das Steckenpferd des Frameworks ist. Da ein konkretes Anwendungsszenario den Rahmen sprengen würde, wird in diesem Artikel ein fiktives Beispiel gewählt, auf welchem man ohne Schwierigkeiten aufbauen kann:

Um einen Benutzer auszusperren, wird in den Anmeldevorgang eingegriffen und dazu anhand des Namens entscheiden, dass dieser Benutzer auf dem Identity Server auf die Route /access-denied weitergeleitet wird. Dies erfolgt, indem eine neue Klasse angelegt und von AuthorizeInteractionResponseGenerator abgeleitet und dann in der HostingExtensions.cs nach Aufruf von AddIdentityServer() mit AddAuthorizeInteraction-ResponseGenerator<Klassenname>() zum Identity Server ergänzt wird.

In der neu angelegten Klasse, welche von AuthorizeInteractionResponesGenerator abgeleitet ist, wird dann noch die Methode ProcessInteraction überschrieben, in der weiterhin der Basis-Aufruf durchgeführt wird. Im Anschluss wird geprüft, ob der Nutzer anhand seines Namens auf die Route /access-denied weitergeleitet wird (s. Listing 5).

Listing 5: Customizing im Identity Server

public override async Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { 
  var baseInteraction = await base.ProcessInteractionAsync(request, consent); 
  if (baseInteraction.IsLogin || baseInteraction.IsError || baseInteraction.IsConsent) 
  { 
    return baseInteraction; 
  } 
  if (request.Subject.Identity.Name == "alice") 
  { 
    var response = new InteractionResponse { RedirectUrl = ("/access-denied") }; 
    return response; 
  } 
  return baseInteraction;
}

Im ersten Moment mag das vielleicht wie eine sinnlose Spielerei wirken, aber wenn ein vollständiges Benutzer-Management z. B. via ASP.NET Identity integriert wurde, kann anhand der Nutzerinformationen überprüft werden, ob z. B. der Anwender sein Passwort ändern muss, und dieser kann auf eine dafür vorgesehene Seite weitergeleitet werden. Diese Einfachheit zeichnet Duende Identity Server unter anderem aus und diese Philosophie zieht sich durch das ganze Framework.

Lessons Learned und Fazit

So einfach der Start mit dem Duende Identity Server auch ist und so leicht sich die ersten Anforderungen im Projekt umsetzen lassen, der Identity Server selbst und auch die Anbindung der Clients sollte keine Nebenbaustelle sein. Zuallererst sollte man sich mit den Konzepten auseinandersetzen, aber auch mit der Funktionalität des Identity Servers. Wie so oft führen viele Wege ans Ziel, aber einmal nicht nachgedacht, hat man sich schnell eine kritische Sicherheitslücke in das System eingebaut, welche zwangsläufig alle angebundenen Clients betrifft.

Einmal nicht nachgedacht, hat man sich eine kritische Sicherheitslücke in das System eingebaut.

Außerdem ist der Identity Server keine Allzwecklösung. Er sollte möglichst leichtgewichtig gehalten werden, damit selten Anpassungen vorgenommen werden müssen und eine hohe Verfügbarkeit und geringe Komplexität sichergestellt wird. Zu Beginn sollte man sich Gedanken machen, welche Informationen von den Nutzern allgemein benötigt werden und welche spezifisch für die einzelnen Clients sind, um späteres aufwändiges Trennen der Daten und viel Migrationsaufwand zu vermeiden.

Bei Anpassungen im Identity Server sollte immer erst geschaut werden, ob es dafür schon vorhandene Lösungen gibt, die ebenfalls Spielraum für Anpassungen bieten, z. B. ASP.NET Core Identity. Weniger Custom Code heißt in dem Fall weniger Wartungsaufwand, weniger Risiken und weniger Kosten.

Zusätzlich sollte man sich rechtzeitig um eine Lösung zum Verwalten von Zertifikaten kümmern, denn wenn das Thema aus dem Blick gerät, sind entweder die Zertifikate abgelaufen und die Anmeldung funktioniert nicht mehr oder die Clients erkennen das Zertifikat vom Provider nicht mehr als vertrauenswürdig.

Abschließend sei daher gesagt, dass der Duende Identity Server zwar einen schnellen Einstieg ermöglicht, besonders wenn man aus der Microsoft-Welt kommt und ASP.NET kein Neuland ist, aber auch nicht die vollumfassende Lösung ist.

Florian Bader & Dustin Baron auf den IT-Tagen 2022

Zum gleichen Thema halten Florian Bader & Dustin Baron einen Vortrag auf den diesjährigen IT-Tagen – der Jahreskonferenz der Informatik Aktuell.

Zentrale Authentifizierung in der Cloud: Self-made Identity
(13.12.2022, 10:00 Uhr)

Autoren

Florian Bader

Florian Bader berät Kunden im Bereich Microsoft .NET, DevOps, Cloud und IoT mit Schwerpunkt in Softwareentwicklung und -architektur. Er wurde von Microsoft als Most Valuable Professional (MVP) für Developer Technologies…
>> Weiterlesen

Dustin Baron

Dustin Baron ist Consultant bei AIT GmbH & Co. KG und hilft Unternehmen bei der erfolgreichen Umsetzung von Softwareprojekten im .NET-Umfeld.
>> Weiterlesen
Das könnte Sie auch interessieren
Kommentare (0)

Neuen Kommentar schreiben