Der vollständige Leitfaden zur Integration eines OIDC-Servers in dein Projekt
Lerne die besten Praktiken zur Integration eines OIDC (OpenID Connect) Servers in dein Projekt kennen und verstehe, wie die Komponenten auf der Bühne miteinander interagieren.
Du kannst in eine Situation geraten, in der du ein zentrales Authentifizierungs- und Autorisierungssystem benötigst, auch bekannt als Identitäts- und Zugriffsverwaltung (IAM) oder Identitätsanbieter (IdP). Manchmal fügen Leute ein Wort hinzu, um das Geschäft zu bezeichnen, wie zum Beispiel Customer IAM und Workforce IAM.
Lassen wir diese ausgefallenen Namen für einen Moment beiseite. Der Bedarf an IAM könnte auftreten, weil deine Anwendung wächst oder du planst, die harte Arbeit von Anfang an an einen Anbieter zu delegieren. Dennoch kommst du an einen Punkt, an dem ein Identitätssystem in dein Projekt integriert werden muss.
Angesichts der Popularität von OAuth 2.0 ist OpenID Connect (OIDC) für viele Entwickler die natürliche Wahl. Da OIDC eine Authentifizierungsschicht ist, die auf OAuth 2.0 basiert, wirst du dich möglicherweise vertraut fühlen, wenn du beginnst, mit OIDC zu arbeiten. Fangen wir an!
Was ist ein OIDC-Server und warum sollte ich einen OIDC-Server integrieren?
Ein OIDC-Server oder Identitätsanbieter ist ein zentrales System, das die Benutzerauthentifizierung und -autorisierung verwaltet. Wie wir in Warum du ein zentrales Identitätssystem für ein Multi-App-Geschäft benötigst besprochen haben, hat ein zentrales Identitätssystem viele Vorteile.
Angenommen, dein Projekt startet mit einer einfachen Webanwendung, die eine eingebaute Authentifizierung hat:
Wenn dein Projekt wächst, musst du eine mobile Version einführen:
Es wäre eine schlechte Erfahrung für Nutzer, wenn sie für jede Anwendung ein Konto erstellen müssten. Da du mit einer Webanwendung begonnen hast, lässt du die mobile Anwendung mit der Webanwendung zur Authentifizierung kommunizieren:
Nun wird ein neuer API-Dienst eingeführt. Da es sich um einen Dienst für zahlende Nutzer handelt, musst du sicherstellen, dass der Nutzer authentifiziert und autorisiert ist, um auf den Dienst zuzugreifen. Um dies zu erreichen, kannst du den Dienst über die Webanwendung proxyen:
Oder du nutzt eine Token-Technologie, um den Nutzer zu authentifizieren, und validierst das Token, indem du mit der Webanwendung im Dienst sprichst. Daher kann die mobile Anwendung den Dienst direkt nutzen:
Die Dinge werden chaotisch. Also entscheidest du dich, die Authentifizierungs- und Autorisierungslogik in einen separaten Dienst aufzuteilen:
Der Refaktorierungsprozess kann schmerzhaft sein. Du wirst bemerken, dass die Komplexität exponentiell zunimmt, wenn du weitere Anwendungen und Dienste zum Projekt hinzufügst. Noch schlimmer ist, dass du möglicherweise mehrere Authentifizierungsmethoden wie passwortloses Einloggen, soziale Logins, SAML usw. pflegen musst.
Deshalb ist es besser, von Anfang an einen Identitätsanbieter einzuführen, wenn du planst, dein Projekt zu skalieren.
Beste Praktiken für die Integration eines OIDC-Servers
Finde einen OIDC-Anbieter
Es gibt viele OIDC-Anbieter auf dem Markt. Du kannst einen basierend auf deinen Anforderungen und Vorlieben wählen. Solange der Anbieter OIDC-konform ist, wird er die gleiche Rolle in deinem Projekt spielen.
Was bedeuten „Subjekt“, „Client“ und „Audience“ in OIDC?
Um das Konzept zu vereinfachen, können wir denken, dass das Subjekt die Einheit ist, die über einen Client auf eine Audience zugreifen möchte.
Schauen wir uns einige typische Szenarien an:
1. Ein Nutzer klickt auf den Anmeldeknopf in einer Webanwendung
In einer traditionellen und serverseitigen gerenderten Webanwendung sind Frontend und Backend gekoppelt. Angenommen, die Webanwendung bedient sowohl Frontend als auch Backend:
- Subjekt: Der Nutzer
- Audience: Der OIDC-Server
- Client: Die Webanwendung
Es mag kontraintuitiv erscheinen, dass die Audience der OIDC-Server ist. Tatsächlich ist dies der Schlüssel, um das SSO-Erlebnis (Single Sign-On) für Endnutzer zu realisieren. Lassen Sie uns ein vereinfachtes Sequenzdiagramm für den Autorisierungscode-Fluss ansehen:
code
ist ein Einmalkode, der gegen verschiedene Tokens wie Zugangstoken, ID-Token und Aktualisierungstoken eingetauscht werden kann. Es ist in Ordnung, wenn du diese Tokens im Moment nicht vollständig verstehst. Im Laufe der Zeit wirst du ein besseres Verständnis von ihnen bekommen.
In dem obigen Fall muss sich der Nutzer nicht erneut anmelden, wenn er zu einer anderen Anwendung wechselt, da der Nutzer (Subjekt) bereits beim OIDC-Server (Audience) authentifiziert wurde.
2. Ein Nutzer verwendet eine Single-Page-Anwendung
In einer Single-Page-Anwendung (oder einer mobilen Anwendung) sind Frontend und Backend getrennt. Angenommen, das Backend ist ein API-Dienst:
- Subjekt: Der Nutzer
- Audience: Der API-Dienst
- Client: Die Single-Page-Anwendung (SPA)
Ein vereinfachtes Sequenzdiagramm mit dem Autorisierungscode-Fluss:
Da der API-Dienst nicht interaktiv ist, muss die SPA das Zugangstoken mit dem API-Dienst als Audience (das aud
im Token) verwenden.
Warum ist der OIDC-Server immer noch eine Audience?
Technisch gesehen kannst du den OIDC-Server aus der Audienceliste entfernen. Da du in den meisten Fällen die Benutzerinformationen vom OIDC-Server benötigst (was erfordert, dass der OIDC-Server die Audience ist), ist es besser, den OIDC-Server immer in die Audienceliste aufzunehmen, wenn es Benutzereingriffe gibt.
Warte, du sagst, dass wir bei einer Autorisierungsanfrage mehrere Audiences haben können?
Exakt! Denke daran, dass OIDC auf OAuth 2.0 aufbaut. Es ist möglich, RFC 8707: Resource Indicators für OAuth 2.0 in der Autorisierungsanfrage zu nutzen, um mehrere Audiences zu spezifizieren. Dies erfordert Unterstützung sowohl vom Grant als auch vom OIDC-Server. Logto unterstützt dieses Feature nativ.
3. Eine Maschine-zu-Maschine-Kommunikation
Angenommen, du hast einen Dienst A, der Dienst B anrufen muss:
- Subjekt: Dienst A
- Audience: Dienst B
- Client: Dienst A
Ein vereinfachtes Sequenzdiagramm mit dem Client Anmeldedaten-Grant:
Wenn Dienst B Dienst A anrufen muss, werden die Rollen einfach getauscht.
Zusammenfassung
- Subjekt: Es kann ein Benutzer, ein Dienst oder eine beliebige Einheit sein, die auf die Audience zugreifen muss.
- Client: Es kann eine Webanwendung, eine mobile Anwendung oder eine beliebige Einheit sein, die die Anfrage initiiert oder im Auftrag des Subjekts handelt.
- Audience: Es kann ein Dienst, eine API oder eine beliebige Einheit sein, die dem Subjekt Zugriff bietet.
Was sind Zugangstokens, ID-Tokens und Aktualisierungstokens?
Es gibt drei Arten von Tokens, auf die du bei der Arbeit mit OIDC stoßen kannst:
- Zugangstoken: Es wird verwendet, um auf die Audience zuzugreifen. Es kann entweder ein JWT (JSON Web Token) oder ein undurchsichtiges Token (normalerweise ein zufälliger String) sein.
- ID-Token: Ein OIDC-spezifisches Token, das Benutzerinformationen enthält. Es ist immer ein JWT. Der Client kann das Token dekodieren, um Benutzerinformationen zu erhalten.
- Aktualisierungstoken: Es wird verwendet, um ein neues Set von Tokens zu erhalten, wenn das Zugangstoken oder ID-Token abläuft.
Für eine detaillierte Erklärung dieser Tokens kannst du auf Verständnis von Aktualisierungstokens, Zugangstokens und ID-Tokens im OIDC-Protokoll verweisen.
Im obigen Szenario 1 und 2 bezieht sich der Begriff Autorisierungsanfrage auf eine Anfrage, um ein Set von Tokens über einen spezifischen Grant zu erhalten.
Wenn alles gut läuft, wird in dem Schritt „Tokentausch mit code
“ ein Satz von Tokens zurückgegeben. Die verfügbaren Tokens im Satz hängen von mehreren Faktoren ab, insbesondere vom scope
Parameter in der Autorisierungsanfrage. Der Einfachheit halber nehmen wir an, dass alle Tokens im Satz zurückgegeben werden. Sobald das Zugangstoken abläuft, kann der Client das Aktualisierungstoken verwenden, um ein neues Set von Tokens ohne Benutzereingriff zu erhalten.
Für Szenario 3 ist es einfacher, da der Client-Anmeldedaten-Grant nur ein Zugangstoken zurückgibt.
Wie geht man mit mehreren Audiences in OIDC um?
Du kannst bemerken, dass jedes Mal nur ein Zugangstoken zurückgegeben wird. Wie können wir den Fall bewältigen, in dem der Client auf mehrere Audiences zugreifen muss?
Es gibt zwei häufige Lösungen:
resource
im Codeaustausch Anforderungsparameter angeben
Wenn der Client den Code gegen Tokens eintauscht, kann er einen resource
Parameter in der Anfrage angeben. Der OIDC-Server wird ein Zugangstoken für die angegebene Audience zurückgeben, falls zutreffend.
Hier ist ein nicht-normatives Beispiel:
Dann wird der OIDC-Server ein Zugangstoken für die API_SERVICE
Audience zurückgeben, falls zutreffend.
Ein Aktualisierungstoken verwenden, um ein neues Zugangstoken zu erhalten
Mit RFC 8707 kann der Client sogar mehrere Audiences angeben, indem der resource
Parameter mehrmals verwendet wird. Jetzt, wenn Aktualisierungstokens im Client verfügbar sind, kann der Client die Audience im resource
Parameter angeben, wenn er das Token aktualisiert.
Hier ist ein nicht-normatives Beispiel:
Es hat den gleichen Effekt wie die vorherige Lösung. Inzwischen sind andere gewährte Audiences weiterhin in zukünftigen Tokenanfragen verfügbar.
Client-Anmeldedaten Grant
Du kannst auch den resource
Parameter im Client-Anmeldedaten Grant verwenden, um die Audience anzugeben. Es gibt kein Problem mit mehreren Audiences in diesem Grant, da du immer ein neues Zugangstoken für eine andere Audience anfordern kannst, indem du einfach eine weitere Tokenanfrage sendest.
Schütze deinen API-Dienst
Der "API-Dienst" im Szenario 2 und der "Dienst B" im Szenario 3 haben eines gemeinsam: Sie müssen das Zugangstoken validieren, um festzustellen, ob die Anfrage autorisiert ist. Abhängig vom Format des Zugangstokens kann der Validierungsprozess variieren.
- Undurchsichtiges Token: Der API-Dienst muss den OIDC-Server anrufen, um das Token zu validieren. Ein Introspektionsendpunkt wird normalerweise vom OIDC-Server zu diesem Zweck bereitgestellt.
- JWT: Der API-Dienst kann das Token lokal validieren, indem er die Signatur und die Claims im Token überprüft. Der OIDC-Server bietet normalerweise einen JSON Web Key Set (JWKS) Endpunkt (
jwks_uri
) an, damit der API-Dienst den öffentlichen Schlüssel zur Überprüfung der Signatur erhält.
Wenn du neu bei JWT bist, kannst du auf Was ist JSON Web Token (JWT)? verweisen. Tatsächlich ist normalerweise keine manuelle Validierung der Signatur und der Ansprüche erforderlich, da es viele Bibliotheken gibt, die dies für dich tun können, wie jose für Node.js und Webbrowser.
Ansprüche überprüfen
Zusätzlich zur Validierung der JWT-Signatur sollte der API-Dienst immer die Ansprüche im Token überprüfen:
iss
: Der Aussteller des Tokens. Es sollte mit der Aussteller-URL des OIDC-Servers übereinstimmen.aud
: Die Audience des Tokens. Es sollte mit dem Audience-Wert des API-Dienstes übereinstimmen (normalerweise ein gültiger URI).exp
: Die Ablaufzeit des Tokens. Der API-Dienst sollte das Token ablehnen, wenn es abgelaufen ist.scope
: Die Geltungsbereiche (Berechtigungen) des Tokens. Der API-Dienst sollte prüfen, ob der erforderliche Geltungsbereich im Token vorhanden ist.
Andere Ansprüche, wie sub
(Subjekt) und iat
(ausgestellt um), sind in einigen Fällen ebenfalls wichtig. Wenn du zusätzliche Sicherheitsmaßnahmen hast, überprüfe die Ansprüche entsprechend.
Autorisierung
Eine unbeantwortete Frage bleibt offen: Wie bestimmen wir, ob ein scope (d.h. Berechtigung) einem Subjekt gewährt werden kann?
Die einzelne Frage führt zu einer ganz neuen Welt der Autorisierung, die über den Rahmen dieses Artikels hinausgeht. Kurz gesagt, es gibt einige gängige Ansätze wie RBAC (Role-Based Access Control) und ABAC (Attribute-Based Access Control). Hier sind einige Ressourcen, um dir den Einstieg zu erleichtern:
- RBAC und ABAC: Die Zugriffssteuerungsmodelle, die du kennen solltest
- RBAC in Logto meistern: Ein umfassendes Praxisbeispiel
Schlussbemerkungen
Die Einführung eines OIDC-Servers in dein Projekt ist ein großer Schritt. Es kann die Sicherheit und Skalierbarkeit deines Projekts erheblich verbessern. Gleichzeitig kann es einige Zeit dauern, die Konzepte und die Interaktionen zwischen den Komponenten zu verstehen.
Die Wahl eines guten OIDC-Anbieters, der deinen Anforderungen und Vorlieben entspricht, kann die Komplexität des Integrationsprozesses erheblich reduzieren, da der Anbieter normalerweise das Gesamtkonzept bietet, einschließlich des OIDC-Servers, Autorisierungsmechanismen, SDKs und der Unternehmensfunktionen, die du möglicherweise in Zukunft benötigst.
Ich hoffe, dieser Leitfaden hilft dir, die Grundlagen der Integration eines OIDC-Servers zu verstehen. Wenn du einen Einstieg suchst, empfehle ich selbstsüchtig Logto, unsere Identitätsinfrastruktur für Entwickler.