Einsatz von OAuth 2.0 für Server-zu-Server-Anwendungen

Das Google OAuth 2.0-System unterstützt Server-zu-Server-Interaktionen, z. B. zwischen einer Webanwendung und einem Google-Dienst. Für dieses Szenario benötigen Sie ein Dienstkonto, das zu Ihrer Anwendung und nicht zu einem einzelnen Endnutzer gehört. Ihre Anwendung ruft Google APIs im Namen des Dienstkontos auf, sodass Nutzer nicht direkt beteiligt sind. Dieses Szenario wird manchmal als „OAuth mit zwei Schritten“ oder „2LO“ bezeichnet. Der zugehörige Begriff „dreibeiniges OAuth“ bezieht sich auf Szenarien, in denen Ihre Anwendung Google APIs im Namen von Endnutzern aufruft und in denen manchmal die Einwilligung des Nutzers erforderlich ist.

Normalerweise verwendet eine Anwendung ein Dienstkonto, wenn sie Google APIs verwendet, um mit eigenen Daten statt mit den Daten eines Nutzers zu arbeiten. Eine Anwendung, die Google Cloud Datastore für die Datenspeicherung verwendet, würde beispielsweise ein Dienstkonto verwenden, um ihre Aufrufe der Google Cloud Datastore API zu authentifizieren.

Google Workspace-Domainadministratoren können Dienstkonten auch domainweite Berechtigungen zum Zugriff auf Nutzerdaten im Namen von Nutzern in der Domain gewähren.

In diesem Dokument wird beschrieben, wie eine Anwendung den OAuth 2.0-Ablauf von Server zu Server mithilfe einer Google APIs-Clientbibliothek (empfohlen) oder HTTP abschließen kann.

Übersicht

Wenn Sie Server-zu-Server-Interaktionen unterstützen möchten, erstellen Sie zuerst ein Dienstkonto für Ihr Projekt in der API Console. Wenn Sie auf Nutzerdaten für Nutzer in Ihrem Google Workspace-Konto zugreifen möchten, delegieren Sie dem Dienstkonto domainweiten Zugriff.

Anschließend bereitet Ihre Anwendung autorisierte API-Aufrufe vor, indem sie mit den Anmeldedaten des Dienstkontos ein Zugriffstoken vom OAuth 2.0-Autorisierungsserver anfordert.

Schließlich kann Ihre Anwendung das Zugriffstoken verwenden, um Google APIs aufzurufen.

Dienstkonto erstellen

Die Anmeldedaten eines Dienstkontos umfassen eine eindeutige generierte E-Mail-Adresse und mindestens ein öffentliches/privates Schlüsselpaar. Wenn die domainweite Delegation aktiviert ist, ist auch eine Client-ID Teil der Anmeldedaten des Dienstkontos.

Wenn Ihre Anwendung in der Google App Engine ausgeführt wird, wird beim Erstellen des Projekts automatisch ein Dienstkonto eingerichtet.

Wenn Ihre Anwendung in der Google Compute Engine ausgeführt wird, wird beim Erstellen des Projekts auch automatisch ein Dienstkonto eingerichtet. Sie müssen jedoch die Bereiche angeben, auf die Ihre Anwendung zugreifen muss, wenn Sie eine Google Compute Engine-Instanz erstellen. Weitere Informationen finden Sie unter Instanz für die Verwendung von Dienstkonten vorbereiten.

Wenn Ihre Anwendung nicht in der Google App Engine oder der Google Compute Engine ausgeführt wird, müssen Sie diese Anmeldedaten in der Google API Consoleabrufen. So generieren Sie Anmeldedaten für ein Dienstkonto oder rufen Sie die bereits generierten öffentlichen Anmeldedaten auf:

Erstellen Sie zunächst ein Dienstkonto:

  1. Öffnen Sie den Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Klicken Sie auf Dienstkonto erstellen .
  4. Geben Sie unter Dienstkontodetails einen Namen, eine ID und eine Beschreibung für das Dienstkonto ein und klicken Sie dann auf Erstellen und fortfahren .
  5. Optional: Wählen Sie unter Diesem Dienstkonto Zugriff auf Projekt gewähren die IAM-Rollen aus, die dem Dienstkonto gewährt werden sollen.
  6. Klicken Sie auf Weiter .
  7. Optional: Fügen Sie unter Benutzern Zugriff auf dieses Dienstkonto gewähren die Benutzer oder Gruppen hinzu, die das Dienstkonto verwenden und verwalten dürfen.
  8. Klicken Sie auf Fertig .

Erstellen Sie als Nächstes einen Dienstkontoschlüssel:

  1. Klicken Sie auf die E-Mail-Adresse für das von Ihnen erstellte Dienstkonto.
  2. Klicken Sie auf die Registerkarte Schlüssel .
  3. Wählen Sie in der Dropdown-Liste Schlüssel hinzufügen die Option Neuen Schlüssel erstellen aus.
  4. Klicken Sie auf Erstellen .

Ihr neues öffentliches/privates Schlüsselpaar wird generiert und auf Ihren Computer heruntergeladen; es dient als einzige Kopie des privaten Schlüssels. Sie sind für die sichere Aufbewahrung verantwortlich. Wenn Sie dieses Schlüsselpaar verlieren, müssen Sie ein neues generieren.

Sie können jederzeit zu  API Console zurückkehren, um die E-Mail-Adresse, die Fingerabdrücke öffentlicher Schlüssel und andere Informationen aufzurufen oder zusätzliche Paare aus öffentlichem/privatem Schlüssel zu generieren. Weitere Informationen zu den Anmeldedaten für Dienstkonten in der API Consolefinden Sie in der Hilfe unter Dienstkonten. API Console

Notieren Sie sich die E-Mail-Adresse des Dienstkontos und speichern Sie die Datei mit dem privaten Schlüssel des Dienstkontos an einem Ort, auf den Ihre Anwendung zugreifen kann. Ihre Anwendung benötigt sie, um autorisierte API-Aufrufe auszuführen.

Domainweite Befugnisse an das Dienstkonto delegieren

Über ein Google Workspace-Konto kann ein Workspace-Administrator der Organisation eine Anwendung dazu autorisieren, im Namen von Nutzern in der Google Workspace-Domain auf Workspace-Nutzerdaten zuzugreifen. Beispielsweise nutzt eine Anwendung, die die Google Calendar API zum Hinzufügen von Ereignissen zu den Kalendern aller Nutzer in einer Google Workspace-Domain verwendet, ein Dienstkonto, um im Namen der Nutzer auf die Google Calendar API zuzugreifen. Das Autorisieren eines Dienstkontos für den Zugriff auf Daten im Namen von Nutzern in einer Domain wird manchmal als „Übertragen domainweiter Befugnisse“ an ein Dienstkonto bezeichnet.

Wenn ein Super Admin der Google Workspace-Domain einem Dienstkonto domainweite Berechtigungen zuweisen möchte, muss er die folgenden Schritte ausführen:

  1. Klicken Sie in der Admin-Konsole Ihrer Google Workspace-Domain auf das Hauptmenü > „Sicherheit“ > „Zugriffs- und Datenkontrolle“ > „API-Steuerung“.
  2. Wählen Sie im Bereich Domainweite Delegierung die Option Domainweite Delegierung verwalten aus.
  3. Klicken Sie auf Neu hinzufügen.
  4. Geben Sie im Feld Client-ID die Client-ID des Dienstkontos ein. Die Client-ID Ihres Dienstkontos finden Sie in der Service accounts page.
  5. Geben Sie im Feld OAuth-Bereiche (durch Kommas getrennt) die Liste der Bereiche ein, auf die Ihre Anwendung Zugriff haben soll. Wenn Ihre Anwendung beispielsweise domainweit vollständigen Zugriff auf die Google Drive API und die Google Calendar API benötigt, geben Sie Folgendes ein: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Klicken Sie auf Autorisieren.

Ihre Anwendung ist jetzt berechtigt, API-Aufrufe als Nutzer in Ihrer Workspace-Domain auszuführen, um Nutzer zu „impersonieren“. Wenn Sie diese delegierten API-Aufrufe vorbereiten, geben Sie den Nutzer, für den Sie sich ausgeben möchten, explizit an.

Vorbereiten eines delegierten API-Aufrufs

Java

Nachdem Sie die E-Mail-Adresse des Clients und den privaten Schlüssel aus der API Consoleabgerufen haben, erstellen Sie mit der Google APIs Client Library for Java ein GoogleCredential-Objekt aus den Anmeldedaten des Dienstkontos und den Bereichen, auf die Ihre Anwendung zugreifen muss. Beispiel:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Wenn Sie eine Anwendung in der Google Cloud-Plattform entwickeln, können Sie stattdessen die Standardanmeldedaten für Anwendungen verwenden. Dies vereinfacht den Vorgang.

Domainweite Befugnisse delegieren

Wenn Sie domainweiten Zugriff auf das Dienstkonto delegiert haben und die Identität eines Nutzerkontos übernehmen möchten, geben Sie die E-Mail-Adresse des Nutzerkontos mit der Methode createDelegated des GoogleCredential-Objekts an. Beispiel:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("[email protected]");

Im obigen Code wird das GoogleCredential-Objekt verwendet, um die createDelegated()-Methode aufzurufen. Das Argument für die createDelegated()-Methode muss ein Nutzer sein, der zu Ihrem Workspace-Konto gehört. Der Code, der die Anfrage stellt, verwendet diese Anmeldedaten, um Google APIs mit Ihrem Dienstkonto aufzurufen.

Python

Nachdem Sie die E-Mail-Adresse des Kunden und den privaten Schlüssel von der API Consoleabgerufen haben, führen Sie mit der Google APIs-Clientbibliothek für Python die folgenden Schritte aus:

  1. Erstellen Sie ein Credentials-Objekt aus den Anmeldedaten des Dienstkontos und den Bereichen, auf die Ihre Anwendung zugreifen muss. Beispiel:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    Wenn Sie eine Anwendung in der Google Cloud-Plattform entwickeln, können Sie stattdessen die Standardanmeldedaten für Anwendungen verwenden. Dies vereinfacht den Vorgang.

  2. Domainweite Befugnisse delegieren

    Wenn Sie domainweiten Zugriff auf das Dienstkonto delegiert haben und die Identität eines Nutzerkontos übernehmen möchten, verwenden Sie die with_subject-Methode eines vorhandenen ServiceAccountCredentials-Objekts. Beispiel:

    delegated_credentials = credentials.with_subject('[email protected]')

Verwenden Sie das Anmeldedatenobjekt, um Google APIs in Ihrer Anwendung aufzurufen.

HTTP/REST

Nachdem Sie die Client-ID und den privaten Schlüssel von der API Consoleerhalten haben, müssen Sie in Ihrer Anwendung die folgenden Schritte ausführen:

  1. Erstellen Sie ein JSON Web Token (JWT, ausgesprochen „jot“), das einen Header, einen Anforderungssatz und eine Signatur enthält.
  2. Fordern Sie ein Zugriffstoken vom Google OAuth 2.0 Authorization Server an.
  3. JSON-Antwort des Autorisierungsservers verarbeiten

In den folgenden Abschnitten wird beschrieben, wie Sie diese Schritte ausführen.

Wenn die Antwort ein Zugriffstoken enthält, können Sie es zum Aufrufen einer Google API verwenden. Wenn die Antwort kein Zugriffstoken enthält, sind JWT und Tokenanfrage möglicherweise nicht richtig formatiert oder das Dienstkonto hat keine Berechtigung zum Zugriff auf die angeforderten Bereiche.

Wenn das Zugriffstoken abläuft, generiert Ihre Anwendung ein weiteres JWT, signiert es und fordert ein weiteres Zugriffstoken an.

Ihre Serveranwendung verwendet ein JWT, um ein Token vom Autorisierungsserver von Google anzufordern, und ruft dann mit dem Token einen Google API-Endpunkt auf. Es ist kein Endnutzer beteiligt.

Im restlichen Teil dieses Abschnitts werden die Details zum Erstellen, Signieren, Erstellen der Zugriffstokenanfrage und zum Umgang mit der Antwort beschrieben.

JWT erstellen

Ein JWT besteht aus drei Teilen: einem Header, einem Anforderungssatz und einer Signatur. Der Header und der Anforderungssatz sind JSON-Objekte. Diese JSON-Objekte werden in UTF-8-Byte serialisiert und dann mit der Base64url-Codierung codiert. Diese Codierung bietet Schutz vor Codierungsänderungen aufgrund wiederholter Codierungsvorgänge. Der Header, der Anspruchssatz und die Signatur werden mit einem Punkt (.) verkettet.

Ein JWT besteht aus folgenden Elementen:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

Der Basisstring für die Signatur sieht so aus:

{Base64url encoded header}.{Base64url encoded claim set}
JWT-Header bilden

Der Header besteht aus drei Feldern, die den Signaturalgorithmus, das Format der Bestätigung und die [Schlüssel-ID des Dienstkontoschlüssels](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) angeben, mit dem das JWT signiert wurde. Algorithmus und Format sind obligatorisch und jedes Feld hat nur einen Wert. Wenn zusätzliche Algorithmen und Formate eingeführt werden, ändert sich dieser Header entsprechend. Die Schlüssel-ID ist optional. Wenn eine falsche Schlüssel-ID angegeben wird, versucht GCP, alle mit dem Dienstkonto verknüpften Schlüssel zu verwenden, um das Token zu überprüfen. Wenn kein gültiger Schlüssel gefunden wird, wird das Token abgelehnt. Google behält sich das Recht vor, Token mit falschen Schlüssel-IDs in Zukunft abzulehnen.

Dienstkonten basieren auf dem RSA SHA-256-Algorithmus und dem JWT-Tokenformat. Die JSON-Darstellung des Headers sieht so aus:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

Die Base64url-Darstellung lautet:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
JWT-Anforderungssatz bilden

Der JWT-Anspruchssatz enthält Informationen zum JWT, einschließlich der angeforderten Berechtigungen (Bereiche), des Ziels des Tokens, des Ausstellers, des Zeitpunkts der Ausstellung des Tokens und der Lebensdauer des Tokens. Die meisten Felder sind Pflichtfelder. Wie der JWT-Header ist auch der JWT-Anforderungssatz ein JSON-Objekt, das zur Berechnung der Signatur verwendet wird.

Erforderliche Ansprüche

Die erforderlichen Ansprüche im JWT-Anforderungssatz sind unten aufgeführt. Sie können in beliebiger Reihenfolge im Anforderungssatz angezeigt werden.

Name Beschreibung
iss Die E-Mail-Adresse des Dienstkontos.
scope Eine durch Leerzeichen getrennte Liste der Berechtigungen, die von der Anwendung angefordert werden.
aud Eine Beschreibung des beabsichtigten Ziels der Behauptung. Bei einer Zugriffstokenanfrage ist dieser Wert immer https://oauth2.googleapis.com/token.
exp Die Ablaufzeit der Bestätigung, angegeben als Sekunden seit 00:00:00 UTC, 1. Januar 1970. Dieser Wert darf maximal eine Stunde nach der Ausstellung liegen.
iat Die Uhrzeit, zu der die Behauptung abgegeben wurde, angegeben in Sekunden seit 00:00:00 UTC, 1. Januar 1970.

Im Folgenden finden Sie eine JSON-Darstellung der erforderlichen Felder in einem JWT-Anforderungssatz:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Weitere Ansprüche

In einigen Fällen kann eine Anwendung die domainweite Delegierung verwenden, um im Namen eines bestimmten Nutzers in einer Organisation zu handeln. Die Berechtigung für diese Art der Identitätsdiebstahl muss gewährt werden, bevor eine Anwendung sich als Nutzer ausgeben kann. Sie wird in der Regel von einem Super Admin verwaltet. Weitere Informationen finden Sie unter Zugriff auf die API mit domainweiter Delegierung verwalten.

Wenn Sie ein Zugriffstoken abrufen möchten, das einer Anwendung delegierten Zugriff auf eine Ressource gewährt, geben Sie die E-Mail-Adresse des Nutzers in den JWT-Claim ein, der als Wert für das Feld sub festgelegt ist.

Name Beschreibung
sub Die E-Mail-Adresse des Nutzers, für den die Anwendung den delegierten Zugriff anfordert.

Wenn eine Anwendung nicht berechtigt ist, sich als Nutzer auszugeben, enthält die Antwort auf eine Zugriffstokenanfrage mit dem Feld sub den Fehler.

Unten sehen Sie ein Beispiel für einen JWT-Anforderungssatz, der das Feld sub enthält:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "[email protected]",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
JWT-Anforderungssatz codieren

Wie der JWT-Header sollte auch der JWT-Anforderungssatz in UTF-8 serialisiert und base64url-sicher codiert werden. Unten sehen Sie ein Beispiel für eine JSON-Darstellung eines JWT-Anforderungssatzes:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Signatur berechnen

Die JSON Web Signature (JWS)-Spezifikation regelt, wie die Signatur für das JWT erzeugt wird. Die Eingabe für die Signatur ist das Byte-Array des folgenden Inhalts:

{Base64url encoded header}.{Base64url encoded claim set}

Der Signaturalgorithmus im JWT-Header muss bei der Berechnung der Signatur verwendet werden. Der einzige vom Google OAuth 2.0-Autorisierungsserver unterstützte Signaturalgorithmus ist RSA mit dem SHA-256-Hash-Algorithmus. Dies wird als RS256 im Feld alg im JWT-Header ausgedrückt.

Signieren Sie die UTF-8-Darstellung der Eingabe mit SHA256withRSA (auch bekannt als RSASSA-PKCS1-V1_5-SIGN mit der SHA-256-Hash-Funktion) mit dem privaten Schlüssel, der aus der Google API Consoleabgerufen wurde. Die Ausgabe ist ein Byte-Array.

Die Signatur muss dann Base64url-codiert sein. Der Header, der Anspruchssatz und die Signatur werden mit einem Punkt (.) verkettet. Das Ergebnis ist das JWT. Sie sollte so aussehen (Zeilenumbrüche zur Verdeutlichung hinzugefügt):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

Unten sehen Sie ein Beispiel für ein JWT vor der Base64url-Codierung:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

Unten sehen Sie ein Beispiel für ein signiertes JWT, das zur Übertragung bereit ist:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Zugriffstoken anfordern

Nachdem das signierte JWT generiert wurde, kann eine Anwendung damit ein Zugriffstoken anfordern. Diese Zugriffstokenanfrage ist eine HTTPS-POST-Anfrage und der Textkörper ist URL-codiert. Die URL ist unten zu sehen:

https://oauth2.googleapis.com/token

Die folgenden Parameter sind in der HTTPS-POST-Anfrage erforderlich:

Name Beschreibung
grant_type Verwenden Sie den folgenden String, der nach Bedarf URL-codiert werden muss: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion Das JWT, einschließlich Signatur.

Unten findest du einen Rohdump der HTTPS-POST-Anfrage, die in einer Zugriffstokenanfrage verwendet wird:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

Unten ist dieselbe Anfrage mit curl zu sehen:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Umgang mit der Antwort

Wenn die JWT- und Zugriffstokenanfrage korrekt formatiert ist und das Dienstkonto die Berechtigung zum Ausführen des Vorgangs hat, enthält die JSON-Antwort des Autorisierungsservers ein Zugriffstoken. Hier ist ein Beispiel für eine Antwort:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

Zugriffstokens können während des durch den Wert expires_in angegebenen Zeitfensters wiederverwendet werden.

Google APIs aufrufen

Java

Führen Sie die folgenden Schritte aus, um Google APIs mit dem GoogleCredential-Objekt aufzurufen:

  1. Erstellen Sie ein Dienstobjekt für die API, die Sie mit dem GoogleCredential-Objekt aufrufen möchten. Beispiel:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Stellen Sie Anfragen an den API-Dienst über die vom Dienstobjekt bereitgestellte Benutzeroberfläche. So listen Sie beispielsweise die Instanzen von Cloud SQL-Datenbanken im Projekt „exciting-example-123“ auf:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Verwende das autorisierte Credentials-Objekt, um Google APIs aufzurufen. Gehe dazu so vor:

  1. Erstellen Sie ein Dienstobjekt für die API, die Sie aufrufen möchten. Sie erstellen ein Dienstobjekt, indem Sie die Funktion build mit dem Namen und der Version der API und dem autorisierten Credentials-Objekt aufrufen. So rufen Sie beispielsweise Version 1beta3 der Cloud SQL Admin API auf:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Stellen Sie Anfragen an den API-Dienst über die vom Dienstobjekt bereitgestellte Benutzeroberfläche. So listen Sie beispielsweise die Instanzen von Cloud SQL-Datenbanken im Projekt „exciting-example-123“ auf:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Nachdem Ihre Anwendung ein Zugriffstoken erhalten hat, können Sie mit dem Token im Namen eines bestimmten Dienst- oder Nutzerkontos eine Google API aufrufen, sofern die von der API erforderlichen Zugriffsbereiche gewährt wurden. Dazu fügen Sie das Zugriffstoken in eine Anfrage an die API ein, indem Sie entweder einen access_token-Abfrageparameter oder einen Authorization-HTTP-Header-Bearer-Wert angeben. Wenn möglich, ist der HTTP-Header vorzuziehen, da Suchstrings in Serverprotokollen in der Regel sichtbar sind. In den meisten Fällen können Sie mit einer Clientbibliothek Aufrufe von Google APIs einrichten, z. B. beim Aufrufen der Drive Files API.

Im OAuth 2.0 Playground können Sie alle Google APIs ausprobieren und sich ihre Bereiche ansehen.

Beispiele für HTTP-GET

Ein Aufruf des Endpunkts drive.files (Drive Files API) mit dem HTTP-Header Authorization: Bearer könnte so aussehen: Sie müssen Ihr eigenes Zugriffstoken angeben:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Hier ist ein Aufruf derselben API für den authentifizierten Nutzer mit dem Abfragestringparameter access_token:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

Beispiele für curl

Sie können diese Befehle mit der Befehlszeilenanwendung curl testen. Hier ein Beispiel, in dem die HTTP-Header-Option verwendet wird (bevorzugt):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Alternativ können Sie auch die Option „Abfragestringparameter“ verwenden:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Ablauf von Zugriffstokens

Vom Google OAuth 2.0-Autorisierungsserver ausgestellte Zugriffstokens laufen nach der vom Wert expires_in angegebenen Dauer ab. Wenn ein Zugriffstoken abläuft, sollte die Anwendung ein weiteres JWT generieren, es signieren und ein weiteres Zugriffstoken anfordern.

JWT-Fehlercodes

Feld error Feld error_description Bedeutung Lösung
unauthorized_client Unauthorized client or scope in request. Wenn Sie versuchen, die domainweite Delegation zu verwenden, ist das Dienstkonto in der Admin-Konsole der Domain des Nutzers nicht autorisiert.

Achten Sie darauf, dass das Dienstkonto auf der Seite Domainweite Delegation der Admin-Konsole für den Nutzer im Anspruch (sub-Feld) autorisiert ist.

Normalerweise dauert es nur wenige Minuten, es kann aber auch bis zu 24 Stunden dauern, bis die Autorisierung für alle Nutzer in Ihrem Google-Konto übernommen wird.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Ein Dienstkonto wurde in der Admin-Konsole mit der E-Mail-Adresse des Kunden und nicht mit der Client-ID (numerisch) autorisiert. Entfernen Sie den Client auf der Seite Domainweite Delegierung in der Admin-Konsole und fügen Sie ihn mit der numerischen ID wieder hinzu.
access_denied (beliebiger Wert) Wenn Sie die domainweite Delegation verwenden, sind mindestens eine oder mehrere der angeforderten Bereiche in der Admin-Konsole nicht autorisiert.

Achten Sie darauf, dass das Dienstkonto auf der Seite Domainweite Delegierung der Admin-Konsole für den Nutzer im Anspruch (sub-Feld) autorisiert ist und alle Bereiche enthält, die Sie im scope-Anspruch Ihres JWT anfordern.

Normalerweise dauert es nur wenige Minuten, es kann aber auch bis zu 24 Stunden dauern, bis die Autorisierung für alle Nutzer in Ihrem Google-Konto übernommen wird.

admin_policy_enforced (beliebiger Wert) Das Google-Konto kann aufgrund der Richtlinien des Google Workspace-Administrators einen oder mehrere der angeforderten Bereiche nicht autorisieren.

Weitere Informationen dazu, wie ein Administrator den Zugriff auf alle oder vertrauliche und eingeschränkte Bereiche einschränken kann, bis der Zugriff Ihrer OAuth-Client-ID ausdrücklich gewährt wird, finden Sie im Hilfeartikel Zugriff externer und interner Apps auf Google Workspace-Daten verwalten.

invalid_client (beliebiger Wert)

Der OAuth-Client oder das JWT-Token ist ungültig oder falsch konfiguriert.

Weitere Informationen finden Sie in der Fehlerbeschreibung.

Prüfe, ob das JWT-Token gültig ist und die richtigen Ansprüche enthält.

Prüfen Sie, ob der OAuth-Client und das Dienstkonto richtig konfiguriert sind und ob Sie die richtige E-Mail-Adresse verwenden.

Prüfe, ob das JWT-Token korrekt ist und für die Client-ID in der Anfrage ausgestellt wurde.

invalid_grant Not a valid email. Der Nutzer ist nicht vorhanden. Prüfen Sie, ob die E-Mail-Adresse im Feld sub korrekt ist.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

In der Regel bedeutet das, dass die lokale Systemzeit nicht korrekt ist. Das kann auch passieren, wenn der exp-Wert mehr als 65 Minuten in der Zukunft liegt oder der exp-Wert niedriger als der iat-Wert ist.iat

Achten Sie darauf, dass die Uhr auf dem System, auf dem das JWT generiert wird, richtig eingestellt ist. Synchronisieren Sie die Uhrzeit bei Bedarf mit dem Google NTP.

invalid_grant Invalid JWT Signature.

Die JWT-Bestätigung ist mit einem privaten Schlüssel signiert, der nicht mit dem Dienstkonto verknüpft ist, das über die E-Mail-Adresse des Clients identifiziert wird, oder der verwendete Schlüssel wurde gelöscht, deaktiviert oder ist abgelaufen.

Alternativ kann die JWT-Assertion falsch codiert sein. Sie muss Base64-codiert sein, ohne Zeilenumbrüche oder Füllzeichen.

Entschlüsseln Sie die JWT-Anforderungsgruppe und prüfen Sie, ob der Schlüssel, mit dem die Behauptung signiert wurde, mit dem Dienstkonto verknüpft ist.

Verwenden Sie eine von Google bereitgestellte OAuth-Bibliothek, um sicherzustellen, dass das JWT korrekt generiert wird.

invalid_scope Invalid OAuth scope or ID token audience provided. Es wurden keine Bereiche angefordert (leere Liste der Bereiche) oder einer der angeforderten Bereiche existiert nicht (d.h. ist ungültig).

Prüfen Sie, ob der Anspruch (das Feld) scope des JWT ausgefüllt ist, und vergleichen Sie die darin enthaltenen Bereiche mit den dokumentierten Bereichen für die APIs, die Sie verwenden möchten, um sicherzustellen, dass keine Fehler oder Tippfehler vorhanden sind.

Die Liste der Bereiche im scope-Anspruch muss durch Leerzeichen und nicht durch Kommas getrennt werden.

disabled_client The OAuth client was disabled. Der Schlüssel, der zum Signieren der JWT-Assertion verwendet wird, ist deaktiviert.

Rufen Sie die Google API Consoleauf und aktivieren Sie unter IAM & Verwaltung > Dienstkonten das Dienstkonto, das die „Schlüssel-ID“ enthält, die zum Signieren der Bestätigung verwendet wurde.

org_internal This client is restricted to users within its organization. Die OAuth-Client-ID in der Anfrage ist Teil eines Projekts, das den Zugriff auf Google-Konten in einer bestimmten Google Cloud-Organisation einschränkt.

Verwenden Sie ein Dienstkonto der Organisation für die Authentifizierung. Bestätigen Sie die Konfiguration des Nutzertyps für Ihre OAuth-Anwendung.

Anhang: Autorisierung über ein Dienstkonto ohne OAuth

Bei einigen Google APIs können Sie autorisierte API-Aufrufe mit einem signierten JWT direkt als Inhabertoken anstelle eines OAuth 2.0-Zugriffstokens ausführen. So können Sie vermeiden, dass eine Netzwerkanfrage an den Autorisierungsserver von Google gesendet wird, bevor Sie einen API-Aufruf vornehmen.

Wenn für die API, die Sie aufrufen möchten, eine Dienstdefinition im GitHub-Repository von Google APIs veröffentlicht wurde, können Sie autorisierte API-Aufrufe mit einem JWT anstelle eines Zugriffstokens ausführen. Anleitung:

  1. Erstellen Sie ein Dienstkonto wie oben beschrieben. Bewahren Sie die JSON-Datei auf, die Sie beim Erstellen des Kontos erhalten.
  2. Erstelle mit einer beliebigen Standard-JWT-Bibliothek, z. B. einer von jwt.io, ein JWT mit einem Header und einer Nutzlast wie im folgenden Beispiel:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "[email protected]",
      "sub": "[email protected]",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • Geben Sie im Feld kid in der Kopfzeile die ID des privaten Schlüssels Ihres Dienstkontos an. Sie finden diesen Wert im Feld private_key_id der JSON-Datei Ihres Dienstkontos.
    • Geben Sie in den Feldern iss und sub die E-Mail-Adresse Ihres Dienstkontos an. Sie finden diesen Wert im Feld client_email der JSON-Datei Ihres Dienstkontos.
    • Geben Sie für das Feld aud den API-Endpunkt an. Beispiel: https://SERVICE.googleapis.com/.
    • Geben Sie für das Feld iat die aktuelle Unix-Zeit und für das Feld exp die Zeit an, die genau 3.600 Sekunden später eintritt, also der Zeitpunkt, zu dem das JWT abläuft.

Signieren Sie das JWT mit RSA-256 und dem privaten Schlüssel in der JSON-Datei Ihres Dienstkontos.

Beispiel:

Java

Mit google-api-java-client und java-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("[email protected]")
        .withSubject("[email protected]")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Mit PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '[email protected]',
           'sub': '[email protected]',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Rufen Sie die API mit dem signierten JWT als Bearer-Token auf:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

Produktübergreifenden Kontoschutz implementieren

Sie sollten außerdem den Kontoübergreifenden Schutz implementieren, indem Sie den Kontoübergreifenden Schutzdienst von Google verwenden. Mit diesem Dienst können Sie Benachrichtigungen zu Sicherheitsereignissen abonnieren, die Ihre Anwendung über wichtige Änderungen am Nutzerkonto informieren. Je nachdem, wie Sie auf Ereignisse reagieren möchten, können Sie dann Maßnahmen ergreifen.

Beispiele für Ereignistypen, die vom geräteübergreifenden Schutzdienst von Google an Ihre App gesendet werden:

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

Auf der Seite Nutzerkonten mit dem produktübergreifenden Kontoschutz schützen finden Sie weitere Informationen zur Implementierung des produktübergreifenden Kontoschutzes und eine vollständige Liste der verfügbaren Ereignisse.