OpenID Connect: Autorisierung interner Anwendungen von benutzerdefinierten bis hin zu Standardanwendungen

Vor ein paar Monaten habe ich einen OpenID Connect-Server implementiert, um den Zugriff für Hunderte unserer internen Anwendungen zu verwalten. Von unseren eigenen Entwicklungen, die im kleineren Maßstab praktisch waren, sind wir zu einem allgemein anerkannten Standard übergegangen. Der Zugriff über den zentralen Dienst vereinfacht monotone Vorgänge erheblich, reduziert die Kosten für die Implementierung von Berechtigungen, ermöglicht es Ihnen, viele vorgefertigte Lösungen zu finden und sich nicht den Kopf bei der Entwicklung neuer Lösungen zu zerbrechen. In diesem Artikel werde ich über diesen Übergang und die Unebenheiten sprechen, die wir schließen konnten.

OpenID Connect: Autorisierung interner Anwendungen von benutzerdefinierten bis hin zu Standardanwendungen

Vor langer Zeit... Wie alles begann

Als es vor einigen Jahren zu viele interne Anwendungen für die manuelle Steuerung gab, haben wir eine Anwendung geschrieben, um den Zugriff innerhalb des Unternehmens zu kontrollieren. Es handelte sich um eine einfache Rails-Anwendung, die eine Verbindung zu einer Datenbank mit Informationen über Mitarbeiter herstellte und in der der Zugriff auf verschiedene Funktionen konfiguriert wurde. Gleichzeitig haben wir das erste SSO ins Leben gerufen, das auf der Überprüfung von Tokens seitens des Clients und des Autorisierungsservers 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 jede interne Anwendung eine beträchtliche Logikebene beschreiben musste und die Mitarbeiterdatenbanken vollständig mit dem Autorisierungsserver synchronisiert waren.

Nach einiger Zeit beschlossen wir, die Aufgabe der zentralen Autorisierung zu vereinfachen. SSO wurde auf den Balancer übertragen. Mit Hilfe von OpenResty wurde Lua eine Vorlage hinzugefügt, die Token überprüfte, wusste, an welche Anwendung die Anfrage ging, und prüfen konnte, ob dort Zugriff bestand. Dieser Ansatz vereinfachte die Aufgabe der Zugriffskontrolle 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.

Ein Problem blieb jedoch ungelöst. Was ist mit Anwendungen, die Informationen über Mitarbeiter benötigen? Es wäre möglich, eine API für den Autorisierungsdienst zu schreiben, aber dann müsste man für jede dieser Anwendungen zusätzliche Logik hinzufügen. Darüber hinaus wollten wir die Abhängigkeit einer unserer selbst geschriebenen Anwendungen, die später in OpenSource übersetzt werden sollten, auf unserem internen Autorisierungsserver beseitigen. Wir werden ein anderes Mal darüber reden. Die Lösung für beide Probleme war OAuth.

nach gemeinsamen Standards

OAuth ist ein verständlicher, allgemein akzeptierter Autorisierungsstandard, aber da allein seine Funktionalität nicht ausreicht, begann man sofort über OpenID Connect (OIDC) nachzudenken. OIDC selbst ist die dritte Implementierung des offenen Authentifizierungsstandards, der in ein Add-on über das OAuth 2.0-Protokoll (ein offenes Autorisierungsprotokoll) eingeflossen ist. Diese Lösung schließt das Problem fehlender Daten über den Endbenutzer und ermöglicht außerdem den Wechsel des Autorisierungsanbieters.

Wir haben uns jedoch nicht für einen bestimmten Anbieter entschieden und beschlossen, die Integration mit OIDC für unseren bestehenden Autorisierungsserver hinzuzufügen. Für diese Entscheidung sprach die Tatsache, dass OIDC hinsichtlich der Endbenutzerautorisierung sehr flexibel ist. Somit war es möglich, die OIDC-Unterstützung auf Ihrem aktuellen Autorisierungsserver zu implementieren.

OpenID Connect: Autorisierung interner Anwendungen von benutzerdefinierten bis hin zu Standardanwendungen

Unsere Art, unseren eigenen OIDC-Server zu implementieren

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

Zur Integration von OIDC ist es notwendig, die aktuellen Benutzerdaten in eine für den Standard verständliche Form zu bringen. Im OIDC wird dies als Ansprüche bezeichnet. Ansprüche sind im Wesentlichen endgültige Felder in der Benutzerdatenbank (Name, E-Mail, Telefonnummer usw.). Existiert Standardliste der Briefmarken, und alles, was nicht in dieser Liste enthalten ist, gilt als benutzerdefiniert. Daher ist der erste Punkt, auf den Sie achten müssen, wenn Sie sich für einen bestehenden OIDC-Anbieter entscheiden möchten, die Möglichkeit der bequemen Anpassung neuer Marken.

Die Gruppe der Kennzeichen wird in der folgenden Teilmenge zusammengefasst: Geltungsbereich. Bei der Autorisierung wird der Zugriff nicht auf bestimmte Marken, sondern auf Bereiche angefordert, auch wenn einige der Marken aus dem Bereich nicht benötigt werden.

2) Die erforderlichen Zuschüsse wurden umgesetzt

Der nächste Teil der OIDC-Integration ist die Auswahl und Implementierung von Berechtigungsarten, den sogenannten Grants. Das weitere Szenario der Interaktion zwischen der ausgewählten Anwendung und dem Autorisierungsserver hängt von der ausgewählten Bewilligung ab. Ein beispielhaftes Schema zur Auswahl des richtigen Zuschusses ist in der folgenden Abbildung dargestellt.

OpenID Connect: Autorisierung interner Anwendungen von benutzerdefinierten bis hin zu Standardanwendungen

Für unseren ersten Antrag verwendeten wir die gebräuchlichste Bewilligung, den Autorisierungscode. Der Unterschied zu anderen besteht darin, dass es dreistufig ist, d. h. wird weiteren Tests unterzogen. Zuerst stellt der Benutzer einen Antrag auf Autorisierungserlaubnis, erhält einen Token – den Autorisierungscode – und fordert dann mit diesem Token, wie bei einem Reiseticket, einen Zugangstoken an. Die gesamte Hauptinteraktion dieses Autorisierungsskripts basiert auf Weiterleitungen zwischen der Anwendung und dem Autorisierungsserver. Sie können mehr über dieses Stipendium lesen hier.

OAuth folgt dem Konzept, dass die nach der Autorisierung erhaltenen Zugriffstoken temporär sein sollten und sich vorzugsweise im Durchschnitt alle 10 Minuten ändern sollten. Bei der Gewährung des Autorisierungscodes handelt es sich um eine dreistufige Überprüfung durch Weiterleitungen. Alle 10 Minuten einen solchen Schritt durchzuführen, ist ehrlich gesagt nicht die angenehmste Aufgabe für das Auge. Um dieses Problem zu lösen, gibt es einen weiteren Zuschuss – Refresh Token, den wir auch in unserem Land verwendet haben. Hier ist alles einfacher. Bei der Verifizierung durch einen anderen Zuschuss wird zusätzlich zum Hauptzugriffstoken ein weiterer ausgegeben – der Refresh-Token, der nur einmal verwendet werden kann und dessen Lebensdauer normalerweise viel länger ist. Wenn mit diesem Aktualisierungstoken die TTL (Time to Live) des Hauptzugriffstokens endet, wird die Anforderung eines neuen Zugriffstokens an den Endpunkt einer anderen Bewilligung gesendet. Der verwendete Refresh Token wird sofort auf Null zurückgesetzt. Diese Prüfung erfolgt in zwei Schritten und kann im Hintergrund, für den Benutzer unmerklich, durchgeführt werden.

3) Richten Sie benutzerdefinierte Datenausgabeformate ein

Nachdem die ausgewählten Zuschüsse umgesetzt wurden, funktioniert die Autorisierung. Es ist erwähnenswert, Daten über den Endbenutzer zu erhalten. OIDC verfügt hierfür über einen separaten Endpunkt, an dem Sie Benutzerdaten mit Ihrem aktuellen Zugriffstoken und dessen Aktualität anfordern können. Und wenn sich die Daten des Benutzers nicht so oft ändern und Sie die aktuellen Daten viele Male verfolgen müssen, können Sie zu einer Lösung wie JWT-Tokens kommen. Auch diese Token werden vom Standard unterstützt. Das JWT-Token selbst besteht aus drei Teilen: Header (Informationen zum Token), Payload (alle erforderlichen Daten) und Signatur (Signatur, das Token wird vom Server signiert und Sie können später die Quelle seiner Signatur überprüfen).

In der OIDC-Implementierung heißt das JWT-Token id_token. Es kann zusammen mit einem normalen Zugriffstoken angefordert werden und es bleibt nur noch die Überprüfung der Signatur. Der Autorisierungsserver verfügt hierfür über einen separaten Endpunkt mit einem Bündel öffentlicher Schlüssel im Format Ctte. Apropos: Es ist erwähnenswert, dass es einen weiteren Endpunkt gibt, der auf dem Standard basiert RFC5785 spiegelt die aktuelle Konfiguration des OIDC-Servers wider. Es enthält alle Endpunktadressen (einschließlich der Adresse des öffentlichen Schlüsselrings, 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"
 ]
}

Somit können Sie mit id_token alle notwendigen Kennzeichen auf die Nutzlast des Tokens übertragen und müssen nicht jedes Mal den Autorisierungsserver kontaktieren, um Benutzerdaten anzufordern. Der Nachteil dieses Ansatzes besteht darin, dass die Änderung der Benutzerdaten vom Server nicht sofort, sondern mit einem neuen Zugriffstoken erfolgt.

Ergebnisse der Umsetzung

Nachdem wir also unseren eigenen OIDC-Server implementiert und anwendungsseitig Verbindungen zu ihm konfiguriert hatten, lösten wir das Problem der Übertragung von Benutzerinformationen.
Da es sich bei OIDC um einen offenen Standard handelt, haben wir die Möglichkeit, einen bestehenden Anbieter oder eine Serverimplementierung zu wählen. Wir haben Keycloak ausprobiert, das sich als sehr komfortabel zu konfigurieren herausstellte. Nach dem Einrichten und Ändern der Verbindungskonfigurationen auf der Anwendungsseite ist es einsatzbereit. Auf der Anwendungsseite müssen lediglich die Verbindungskonfigurationen geändert werden.

Über bestehende Lösungen sprechen

Innerhalb unserer Organisation haben wir als erster OIDC-Server eine eigene 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. Für die Entscheidung, einen eigenen Server zu implementieren, sprachen seitens der Anbieter Bedenken hinsichtlich des Fehlens der erforderlichen Funktionalität sowie des Vorhandenseins eines alten Systems, in dem es für einige Dienste und vieles mehr unterschiedliche benutzerdefinierte Berechtigungen gab Daten über Mitarbeiter waren bereits gespeichert. In vorgefertigten Implementierungen gibt es jedoch Annehmlichkeiten für die Integration. Keycloak verfügt beispielsweise über ein eigenes Benutzerverwaltungssystem und die Daten werden direkt darin gespeichert, sodass es nicht schwer sein wird, Ihre Benutzer dort zu überholen. Zu diesem Zweck verfügt Keycloak über eine API, mit der Sie alle erforderlichen Übertragungsaktionen vollständig durchführen können.

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

Keycloak und Ory Hydra sind nicht die einzigen Lösungen von der Stange. Wählen Sie am besten eine von der OpenID Foundation zertifizierte Implementierung. Diese Lösungen verfügen normalerweise über ein OpenID-Zertifizierungsabzeichen.

OpenID Connect: Autorisierung interner Anwendungen von benutzerdefinierten bis hin zu Standardanwendungen

Vergessen Sie auch nicht die bestehenden kostenpflichtigen Anbieter, wenn Sie Ihren OIDC-Server nicht behalten möchten. Heute gibt es viele gute Möglichkeiten.

Was weiter

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

Mehr

jwt.io – guter Service zur Validierung von JWT-Tokens
openid.net/developers/certified - Liste zertifizierter OIDC-Implementierungen

Source: habr.com

Kommentar hinzufügen