OpenID Connect: Autorisierung interner Anwendungen von generisch zu standard

Vor einigen Monaten habe ich einen OpenID Connect-Server implementiert, um den Zugriff auf Hunderte unserer internen Anwendungen zu steuern. Von unseren eigenen Entwicklungen, die in kleinerem Maßstab praktisch sind, sind wir zum allgemein akzeptierten Standard übergegangen. Der Zugriff über einen zentralen Dienst vereinfacht monotone Vorgänge erheblich, senkt die Kosten für die Implementierung von Berechtigungen, ermöglicht es Ihnen, viele vorgefertigte Lösungen zu finden und Ihr Gehirn bei der Entwicklung neuer Lösungen nicht zu beschädigen. In diesem Artikel werde ich über diesen Übergang und die Unebenheiten sprechen, die wir füllen konnten.

Intro

Es war einmal ... Wie alles begann


Vor einigen Jahren, als es zu viele interne Anwendungen für die manuelle Steuerung gab, haben wir eine Anwendung für die Zugriffskontrolle innerhalb des Unternehmens geschrieben. Es war eine einfache Rails-Anwendung, die mit einer Datenbank mit Informationen zu Mitarbeitern verbunden war, in der der Zugriff auf verschiedene Funktionen konfiguriert wurde. Dann haben wir das erste SSO ausgelöst, das auf der Überprüfung der Token vom Client und vom Autorisierungsserver basierte. Das Token wurde in verschlüsselter Form mit mehreren Parametern übertragen und auf dem Autorisierungsserver überprüft. Dies war nicht die bequemste Option, da für jede interne Anwendung eine beträchtliche Logikschicht beschrieben werden musste und die Basis der Mitarbeiter vollständig mit dem Autorisierungsserver synchronisiert war.

Nach einiger Zeit haben wir beschlossen, die Aufgabe der zentralisierten Autorisierung zu vereinfachen. SSO wird an den Balancer übertragen. Mit OpenResty auf Lua fügten sie eine Vorlage hinzu, die Token überprüfte, wusste, in welcher Anwendung sich die Anforderung befand, und überprüfen konnte, ob dort Zugriff vorhanden war. Dieser Ansatz vereinfachte die Kontrolle des Zugriffs auf interne Anwendungen erheblich - im Code jeder Anwendung war es nicht mehr erforderlich, zusätzliche Logik zu beschreiben. Infolgedessen haben wir den Datenverkehr extern geschlossen, und die Anwendung selbst wusste nichts über die Autorisierung.

Eines der Probleme blieb jedoch ungelöst. Was ist mit Anwendungen, die Informationen über Mitarbeiter benötigen? Sie könnten eine API für den Autorisierungsdienst schreiben, müssten dann aber für jede solche Anwendung zusätzliche Logik hinzufügen. Darüber hinaus wollten wir die Abhängigkeit von einer unserer selbst geschriebenen Anwendungen auf unserem internen Autorisierungsserver beseitigen, die sich weiter an der Übersetzung in OpenSource orientiert. Wir werden ein anderes Mal über ihn sprechen. Die Lösung für beide Probleme war OAuth.

Zu allgemein anerkannten Standards


OAuth ist ein verständlicher, allgemein anerkannter Autorisierungsstandard. Da seine Funktionalität jedoch nicht ausreicht, wurde OpenID Connect (OIDC) sofort in Betracht gezogen. OIDC selbst ist die dritte Implementierung eines offenen Authentifizierungsstandards, der über das OAuth 2.0-Protokoll (Open Authorization Protocol) in das Add-In übertragen wurde. Diese Lösung schließt das Problem des Mangels an Daten über den Endbenutzer und ermöglicht auch den Wechsel des Autorisierungsanbieters.

Wir haben jedoch keinen bestimmten Anbieter ausgewählt und beschlossen, die Integration mit OIDC für unseren vorhandenen Autorisierungsserver hinzuzufügen. Für eine solche Lösung ist OIDC sehr flexibel in Bezug auf die Autorisierung des Endbenutzers. Somit war es möglich, die OIDC-Unterstützung auf Ihrem aktuellen Autorisierungsserver zu implementieren.

Bild

Unser Weg, unseren eigenen OIDC-Server zu implementieren


1) Sie brachten die Daten in die gewünschte Form


Um OIDC zu integrieren, müssen Sie aktuelle Benutzerdaten auf eine Weise bereitstellen, die für den Standard verständlich ist. In OIDC wird dies als Ansprüche bezeichnet. Marken sind im Wesentlichen Endfelder in der Benutzerdatenbank (Name, E-Mail, Telefon usw.). Es gibt eine Standardliste von Marken , und alles, was nicht in dieser Liste enthalten ist, wird als benutzerdefiniert betrachtet. Daher ist der erste Punkt, auf den Sie achten müssen, wenn Sie einen vorhandenen OIDC-Anbieter auswählen möchten, die Möglichkeit, neue Marken bequem anzupassen.

Die Markengruppe wird in der nächsten Teilmenge zusammengefasst - Scope. Während der Autorisierung wird der Zugriff nicht auf bestimmte Marken, nämlich auf Bereiche, angefordert, auch wenn einige der Kennzeichen aus dem Bereich nicht benötigt werden.

2) Die erforderlichen Zuschüsse umgesetzt


Der nächste Teil der OIDC-Integration ist die Auswahl und Implementierung von Berechtigungsarten, den sogenannten Grants. Das weitere Szenario der Interaktion der ausgewählten Anwendung mit dem Autorisierungsserver hängt von der ausgewählten Gewährung ab. Ein ungefähres Schema für die Auswahl des richtigen Zuschusses ist in der folgenden Abbildung dargestellt.

Bild

Für unsere erste Bewerbung haben wir die häufigste Finanzhilfe verwendet - den Autorisierungscode. Sein Unterschied zu anderen besteht darin, dass es dreistufig ist, d.h. besteht zusätzliche Überprüfung. Zuerst stellt der Benutzer eine Autorisierungserlaubnis an, erhält einen Token - Autorisierungscode und fordert dann mit diesem Token wie mit einem Reiseticket ein Zugriffstoken an. Die gesamte Hauptinteraktion dieses Autorisierungsszenarios basiert auf Weiterleitungen zwischen der Anwendung und dem Autorisierungsserver. Lesen Sie mehr über diesen Zuschuss hier .

OAuth hält an dem Konzept fest, dass nach der Autorisierung erhaltene Zugriffstoken vorübergehend sein und sich vorzugsweise durchschnittlich alle 10 Minuten ändern sollten. Die Erteilung des Autorisierungscodes erfolgt in drei Schritten durch Weiterleitungen. Dieser Schritt alle 10 Minuten ist offen gesagt keine angenehme Erfahrung für die Augen. Um dieses Problem zu lösen, gibt es einen weiteren Zuschuss - Refresh Token, den wir ebenfalls bereitgestellt haben. Hier ist alles einfacher. Während des Tests wird von einem anderen Grant zusätzlich zum Hauptzugriffstoken ein weiteres ausgegeben - das Aktualisierungstoken, das nur einmal verwendet werden kann und dessen Lebensdauer in der Regel erheblich länger ist. Wenn mit diesem Aktualisierungstoken die TTL (Time to Live) des Hauptzugriffstokens endet, wird eine Anforderung für ein neues Zugriffstoken an den Endpunkt einer anderen Berechtigung gesendet. Das verwendete Aktualisierungstoken wird sofort zurückgesetzt.Eine solche Prüfung erfolgt in zwei Schritten und kann für den Benutzer unsichtbar im Hintergrund durchgeführt werden.

3) Benutzerdefinierte Ausgabeformate für Benutzerdaten


Nachdem die ausgewählten Zuschüsse implementiert wurden, funktioniert die Autorisierung. Erwähnenswert ist der Empfang von Daten über den Endbenutzer. OIDC verfügt hierfür über einen separaten Endpunkt, auf dem Sie Benutzerdaten mit Ihrem aktuellen Zugriffstoken und bei Bedarf anfordern können. Und wenn sich die Benutzerdaten nicht so oft ändern und Sie viele Male nach dem aktuellen Stand suchen müssen, können Sie eine Entscheidung wie bei JWT-Token treffen. Diese Token werden auch vom Standard unterstützt. Das JWT-Token selbst besteht aus drei Teilen: Header (Informationen zum Token), Nutzdaten (alle erforderlichen Daten) und Signatur (Signatur, Token wird vom Server signiert und Sie können die Quelle seiner Signatur in Zukunft überprüfen).

In einer OIDC-Implementierung heißt ein JWT-Token id_token. Es kann zusammen mit einem regulären Zugriffstoken angefordert werden. Sie müssen lediglich die Signatur überprüfen. Der Autorisierungsserver verfügt hierfür über einen separaten Endpunkt mit einer Reihe öffentlicher Schlüssel im JWK- Format . In diesem Zusammenhang ist zu erwähnen, dass es einen weiteren Endpunkt gibt, der auf dem RFC5785- Standard basiert und die aktuelle Konfiguration des OIDC-Servers widerspiegelt. Es enthält alle Adressen von Endpunkten (einschließlich der Adresse des öffentlichen Schlüsselbunds, der zum Signieren verwendet wird), unterstützte Marken und Bereiche, verwendete Verschlüsselungsalgorithmen, unterstützte Zuschüsse usw.

Zum Beispiel bei Google:
{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}


Mit id_token können Sie also alle erforderlichen Kennzeichen auf die Nutzdaten des Tokens übertragen und nicht jedes Mal den Autorisierungsserver kontaktieren, um Daten über den Benutzer anzufordern. Der Nachteil dieses Ansatzes besteht darin, dass das Ändern von Benutzerdaten vom Server nicht sofort erfolgt, sondern mit einem neuen Zugriffstoken.

Ergebnisse der Umsetzung


Nachdem wir unseren eigenen OIDC-Server implementiert und auf der Anwendungsseite Verbindungen zu ihm hergestellt hatten, lösten wir das Problem der Übertragung von Benutzerinformationen.
Da OIDC ein offener Standard ist, haben wir die Möglichkeit, einen vorhandenen Anbieter oder eine Serverimplementierung auszuwählen. Wir haben Keycloak ausprobiert, das sich als sehr bequem zu konfigurieren herausstellte. Nach dem Einrichten und Ändern der Verbindungskonfigurationen auf der Anwendungsseite ist es betriebsbereit. Auf der Anwendungsseite bleibt nur die Verbindungskonfiguration zu ändern.

Apropos bestehende Lösungen


Als Teil unserer Organisation haben wir als erster OIDC-Server unsere Implementierung zusammengestellt, die bei Bedarf ergänzt wurde. Nach einer detaillierten Überprüfung anderer vorgefertigter Lösungen können wir sagen, dass dies ein strittiger Punkt ist. Bedenken der Anbieter hinsichtlich des Mangels an erforderlichen Funktionen dienten als Lösung für die Implementierung ihres Servers sowie des Vorhandenseins eines alten Systems, in dem für einige Dienste verschiedene benutzerdefinierte Berechtigungen vorhanden waren und eine Vielzahl von Daten über Mitarbeiter gespeichert wurden. In vorgefertigten Implementierungen ist die Integration jedoch bequem. Zum Beispiel hat Keycloak ein eigenes Benutzerverwaltungssystem und Daten werden direkt darin gespeichert, und es wird nicht schwierig sein, seine Benutzer dort zu überholen. Zu diesem Zweck verfügt Keycloak über eine API, mit der Sie alle für die Übertragung erforderlichen Schritte vollständig implementieren können.

Ein weiteres Beispiel für eine zertifizierte, meiner Meinung nach interessante Implementierung ist Ory Hydra. Es ist insofern interessant, als es aus verschiedenen Komponenten besteht. Für die Integration müssen Sie Ihren Benutzerverwaltungsdienst mit seinem Autorisierungsdienst verknüpfen und bei Bedarf erweitern.

Keycloak und Ory Hydra sind nicht die einzigen schlüsselfertigen Lösungen. Wählen Sie am besten eine zertifizierte OpenID Foundation-Implementierung aus. In der Regel verfügen solche Lösungen über ein OpenID-Zertifizierungsabzeichen.

Openid-Zertifizierung


Vergessen Sie auch nicht die vorhandenen kostenpflichtigen Anbieter, wenn Sie Ihren OIDC-Server nicht behalten möchten. Bisher gibt es viele gute Optionen.

Was weiter


In naher Zukunft werden wir den Verkehr zu internen Diensten auf andere Weise sperren. Wir planen, unser aktuelles SSO mit OpenResty auf dem Balancer auf einen auf OAuth basierenden Proxy zu übertragen. Hier gibt es auch viele vorgefertigte Lösungen, zum Beispiel:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Zusätzliche Materialien


jwt.io - guter Service zum Überprüfen von
openid.net/developers/certified JWT-Token - Liste zertifizierter OIDC-Implementierungen

All Articles