Deutsch
  • oauth
  • jwt
  • api
  • security
  • authentication
  • authorization
  • machine-to-machine

Sichere deine API-Ressourcen für die Kommunikation zwischen Maschinen

Lerne, wie du OAuth 2.0 und JWT nutzen kannst, um deine API-Ressourcen für die Kommunikation zwischen Maschinen zu sichern.

Gao
Gao
Founder

Beim Erstellen eines Projekts, das mehrere Dienste umfasst, ist die Sicherheit der API-Ressourcen eine kritische Angelegenheit. In diesem Artikel zeige ich dir, wie du OAuth 2.0 und JWT nutzen kannst, um die Kommunikation zwischen Diensten (Machine-to-Machine) zu sichern, und wie du rollenbasierte Zugriffskontrolle (RBAC) anwenden kannst, um das Prinzip des geringsten Privilegs einzuhalten.

Erste Schritte

Um mitzumachen, nehme ich an, dass du die folgenden Voraussetzungen hast:

  • Ein Logto-Cloud-Konto oder eine selbst gehostete Logto-Instanz
  • Mindestens zwei Dienste, die miteinander kommunizieren müssen

Zum Demonstrationszweck nehmen wir an, dass wir die folgenden Dienste haben:

  • Ein Einkaufswagen-Dienst, der APIs bereitstellt, um Einkaufswagen zu verwalten
    • Endpunkt: https://cart.example.com/api
  • Ein Zahlungsdienst, der APIs bereitstellt, um Zahlungen zu verarbeiten
    • Endpunkt: https://payment.example.com/api

Authentifizierungsablauf

Nun muss unser Einkaufswagen-Dienst den Zahlungsdienst aufrufen, um Zahlungen zu verarbeiten. Der Authentifizierungsablauf ist wie folgt:

Einige Schlüsselkonzepte im obigen Diagramm:

  • JWT (RFC 7519): JSON Web Token. Siehe unseren vorherigen Artikel für eine Einführung in JWT.
  • JWK (RFC 7517): JSON Web Key, der verwendet wird, um die Signatur eines JWT zu verifizieren. Ein JWK-Set ist eine Sammlung von JWKs.
  • "client_credentials" Grant (RFC 6749): Ein Grant-Typ in OAuth 2.0. Er verwendet die Client-Anmeldeinformationen, um ein Zugriffstoken zu erhalten. Wir werden die Details in den folgenden Abschnitten demonstrieren.

Jeder Teilnehmer im obigen Diagramm hat eine Rolle im Authentifizierungsablauf:

  • Einkaufswagen-Dienst: Der Client, der den Zahlungsdienst aufrufen muss. Obwohl es ein Dienst ist, ist es immer noch ein Client im Kontext von OAuth 2.0, und wir nennen solche Clients „Machine-to-Machine-Anwendungen“ in Logto.
  • Logto: Der OAuth 2.0-Autorisierungsserver, der Zugriffstokens ausgibt.
  • Zahlungsdienst: Die API-Ressource, die APIs bereitstellt, um Zahlungen zu verarbeiten.

Gehen wir den Authentifizierungsablauf Schritt für Schritt durch.

Erste Einrichtung

Um den Authentifizierungsablauf durchzuführen, müssen wir eine Machine-to-Machine-App (Einkaufswagen-Dienst) und eine API-Ressource (Zahlungsdienst) in Logto erstellen.

API-Ressource erstellen

Da unser Einkaufswagen-Dienst beim Durchführen der Authentifizierung über die API des Zahlungsdienstes Bescheid wissen muss, müssen wir zuerst eine API-Ressource erstellen. Gehe zur Logto-Konsole, klicke im linken Seitenbereich auf API-Ressourcen und klicke auf API-Ressource erstellen. Im geöffneten Dialog bieten wir einige Tutorials, um dir den Einstieg zu erleichtern. Du kannst auch auf Weiter ohne Tutorial klicken, um es zu überspringen.

Gib den API-Namen und die Kennung ein, zum Beispiel Zahlungsdienst und https://payment.example.com/api, und klicke dann auf API-Ressource erstellen.

Nach dem Erstellen der API-Ressource wirst du zur Detailseite weitergeleitet. Wir können sie vorerst so belassen.

Machine-to-Machine-App erstellen

Klicke im linken Seitenbereich auf Anwendungen und klicke auf Anwendung erstellen. Im geöffneten Dialog finde die Machine-to-Machine-Karte und klicke auf Starten.

Gib den Anwendungsnamen ein, zum Beispiel Einkaufswagen-Dienst, und klicke auf Anwendung erstellen. Ein interaktiver Guide wird angezeigt, der dir beim Einrichten der Anwendung hilft. Du kannst dem Guide folgen, um die grundlegende Nutzung zu verstehen, oder auf Fertig und beenden klicken, um es zu überspringen.

Zugriffstoken anfordern

Da Machine-to-Machine-Anwendungen als sicher angenommen werden (z.B. sie sind in einem privaten Netzwerk bereitgestellt), können wir den OAuth 2.0 "client_credentials" Grant verwenden, um ein Zugriffstoken zu erhalten. Es verwendet Basic Authentication, um den Client zu authentifizieren:

  • Die Anforderungs-URL ist der Token-Endpunkt deiner Logto-Instanz. Du kannst ihn unter dem Tab Erweiterte Einstellungen auf der Detailseite der Machine-to-Machine-App finden und kopieren.
  • Die Anforderungsmethode ist POST.
  • Der Anforderungs-Content-Type-Header ist application/x-www-form-urlencoded.
  • Für den Authorization-Header ist der Wert Basic <base64(app_id:app_secret)>, wobei app_id und app_secret die App-ID und das App-Geheimnis der Machine-to-Machine-App sind. Du kannst sie auf der Anwendungsdetailseite finden.
  • Der Anforderungstext muss den Grant-Typ und die API-Kennung angeben. Zum Beispiel grant_type=client_credentials&resource=https://payment.example.com/api.
    • grant_type=client_credentials: Der konstante Wert für den "client_credentials" Grant.
    • resource=https://payment.example.com/api: Die API-Kennung der API-Ressource, die der Client zugreifen möchte.
    • Wenn die Anwendung mit Berechtigungen (Scopes) autorisiert werden muss, kannst du auch die Scopes im Anforderungstext angeben. Zum Beispiel scope=read:payment write:payment. Wir behandeln Scopes später.

Hier ist ein Beispiel für die Anforderung mit curl:

Eine erfolgreiche Antwort könnte so aussehen:

Anfrage mit Autorisierungsheader senden

Nun haben wir das Zugriffstoken und können es dem Authorization-Header der Anfrage an die API-Ressource anhängen. Zum Beispiel, wenn wir die POST /payments API des Zahlungsdienstes aufrufen wollen, können wir die folgende Anfrage senden:

JWT validieren

Du magst bemerken, dass der Zahlungsdienst das JWT mit dem JWK-Set validieren muss und möglicherweise einen lokalen JWK-Cache hat, um zu vermeiden, dass das JWK-Set jedes Mal von Logto abgerufen wird. Zum Glück gibt es aufgrund der Popularität von JWT viele Bibliotheken, die dir mit wenigen Codezeilen helfen können, das Ziel zu erreichen.

Diese Bibliotheken werden normalerweise "jose" (JavaScript Object Signing and Encryption) oder "jsonwebtoken" genannt. Zum Beispiel können wir in Node.js jose verwenden, um das JWT zu validieren:

Wenn die Validierung erfolgreich ist, wird die Variable payload die decodierte JWT-Payload sein. Andernfalls wird ein Fehler ausgelöst.

Rollenbasierte Zugriffskontrolle anwenden

Nun haben wir die Kommunikation zwischen dem Einkaufswagen-Dienst und dem Zahlungsdienst erfolgreich gesichert. Der Authentifizierungsablauf stellt jedoch nur sicher, dass der Client der tatsächliche Einkaufswagen-Dienst ist, garantiert jedoch nicht, dass der Einkaufswagen-Dienst eine Erlaubnis hat, Aktionen auf dem Zahlungsdienst auszuführen.

Angenommen, wir wollen dem Einkaufswagen-Dienst erlauben, Zahlungen zu erstellen, aber nicht, Zahlungen zu lesen.

Berechtigungen definieren

In Logto sind "Scopes" und "Berechtigungen" austauschbar. Gehe zur Detailseite der API-Ressource des Zahlungsdienstes und navigiere zum Tab Berechtigungen. Es sollte jetzt leer sein. Klicke auf Berechtigung erstellen, gib read:payment als den Berechtigungsnamen ein und Zahlungen lesen als die Berechtigungserklärung. Dann klicke auf Berechtigung erstellen.

Wiederhole die obigen Schritte, um eine weitere Berechtigung mit dem Namen write:payment und der Beschreibung Zahlungen erstellen zu erstellen.

Rolle für Machine-to-Machine erstellen

Eine Rolle ist eine Gruppe von Berechtigungen. In Logto können Machine-to-Machine-Anwendungen Rollen zugewiesen werden, um Berechtigungen zu gewähren. Klicke im linken Seitenbereich auf "Rollen" und klicke auf Rolle erstellen.

  1. Gib checkout als Rollennamen ein und Checkout-Dienst als Rollenbeschreibung.
  2. Klicke auf Mehr Optionen anzeigen. Wähle "Machine-to-Machine-App-Rolle" als Rollentyp aus.
  3. Im Abschnitt "Zugewiesene Berechtigungen" klicke auf das Pfeilsymbol links vom API-Ressourcennamen (Zahlungsdienst) und wähle die write:payment-Berechtigung aus.
    Rolle erstellen
  4. Klicke auf Rolle erstellen.
  5. Da wir bereits eine Machine-to-Machine-App (Einkaufswagen-Dienst) haben, können wir im nächsten Schritt direkt die Rolle zuweisen. Markiere das Kontrollkästchen links neben dem App-Namen (Einkaufswagen-Dienst) und klicke auf Anwendungen zuweisen.
Rolle zu Anwendung zuweisen

Zugriffstoken mit Scopes anfordern

Neben den Anforderungstextparametern, die wir in Zugriffstoken anfordern erwähnt haben, können wir auch die Scopes im Anforderungstext angeben. Zum Beispiel, wenn wir die Berechtigung write:payment anfordern wollen, können wir die folgende Anfrage senden:

Um mehrere Scopes anzufordern, kannst du sie mit Leerzeichen trennen. Zum Beispiel scope=write:payment read:payment.

Scopes validieren

Wenn eine Aktion die Berechtigung write:payment im Zahlungsdienst benötigt, können wir die Scopes validieren, indem wir feststellen, dass der scope-Anspruch der JWT-Payload:

Fazit

Wenn du den Zugriff auf den Einkaufswagen-Dienst schützen möchtest, kannst du denselben Authentifizierungsablauf anwenden. Dieses Mal ist der Einkaufswagen-Dienst die API-Ressource, und der Client ist ein anderer Dienst, der Zugriff benötigt.

Mit Logto sind deine API-Ressourcen mit OAuth 2.0 und JWT gesichert, und du kannst das Prinzip des geringsten Privilegs durch die Anwendung von rollenbasierter Zugriffskontrolle einhalten. Außerdem kannst du Logto verwenden, um deine Benutzer und deren Berechtigungen zu verwalten und sogar mit Drittanbieter-Identitätsanbietern zu integrieren.