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

Das Google OAuth 2.0-System unterstützt Interaktionen zwischen Servern, beispielsweise zwischen einer Webanwendung und einem Google-Dienst. Für dieses Szenario benötigen Sie ein Dienstkonto. Dieses Konto gehört zu Ihrer Anwendung und nicht zu einem bestimmten Endnutzer. Ihre Anwendung ruft Google APIs im Namen des Dienstkontos auf, sodass Nutzer nicht direkt beteiligt sind. Dieses Szenario wird manchmal als "zweibeiniges OAuth" oder "2LO" bezeichnet. Der verwandte 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.

In der Regel verwendet eine Anwendung ein Dienstkonto, wenn sie Google APIs nutzt, um mit ihren eigenen Daten und nicht mit den Daten eines Nutzers zu arbeiten. Beispielsweise verwendet eine Anwendung, die Google Cloud Datastore für die Datenpersistenz nutzt, ein Dienstkonto, um ihre Aufrufe an die Google Cloud Datastore API zu authentifizieren.

Google Workspace-Domainadministratoren können auch Dienstkonten domainweite Berechtigungen erteilen, damit sie im Namen von Nutzern in der Domain auf Nutzerdaten zugreifen können.

In diesem Dokument wird beschrieben, wie eine Anwendung den Server-zu-Server-OAuth 2.0-Vorgang mithilfe einer Google APIs-Clientbibliothek (empfohlen) oder HTTP ausführen kann.

Überblick

Erstellen Sie zuerst ein Dienstkonto für Ihr Projekt im API Console, um Server-zu-Server-Interaktionen zu unterstützen. Wenn Sie auf Nutzerdaten für Nutzer in Ihrem Google Workspace-Konto zugreifen möchten, delegieren Sie den domainweiten Zugriff an das Dienstkonto.

Anschließend bereitet sich die Anwendung auf autorisierte API-Aufrufe vor. Dabei wird mithilfe der Anmeldedaten des Dienstkontos ein Zugriffstoken vom OAuth 2.0-Authentifizierungsserver angefordert.

Schließlich kann Ihre Anwendung das Zugriffstoken zum Aufrufen von Google APIs verwenden.

Dienstkonto erstellen

Zu den Anmeldedaten eines Dienstkontos gehören eine generierte E-Mail-Adresse, die eindeutig ist, und mindestens ein Paar aus öffentlichem und privatem Schlüssel. Wenn die domainweite Delegierung aktiviert ist, ist auch eine Client-ID Teil der Anmeldedaten des Dienstkontos.

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

Wenn Ihre Anwendung in Google Compute Engine ausgeführt wird, wird beim Erstellen Ihres Projekts ebenfalls automatisch ein Dienstkonto eingerichtet. Sie müssen jedoch beim Erstellen einer Google Compute Engine-Instanz die Bereiche angeben, auf die Ihre Anwendung Zugriff benötigt. Weitere Informationen finden Sie unter Instanz zur Verwendung von Dienstkonten vorbereiten.

Wenn Ihre Anwendung nicht in Google App Engine oder Google Compute Engine ausgeführt wird, müssen Sie diese Anmeldedaten im Google API Consoleabrufen. So generieren Sie Dienstkonto-Anmeldedaten oder rufen 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, Fingerabdrücke öffentlicher Schlüssel und andere Informationen anzusehen oder zusätzliche öffentliche/private Schlüsselpaare zu generieren. Weitere Informationen zu Dienstkonto-Anmeldedaten in der API Consolefinden Sie in der API Console-Hilfe unter Dienstkonten.

Notieren Sie sich die E-Mail-Adresse des Dienstkontos und speichern Sie die private Schlüsseldatei des Dienstkontos an einem Ort, auf den Ihre Anwendung zugreifen kann. Ihre Anwendung benötigt sie, um autorisierte API-Aufrufe durchzuführen.

Domainweite Befugnisse an das Dienstkonto delegieren

Mit einem Google Workspace-Konto kann ein Workspace-Administrator der Organisation eine Anwendung autorisieren, im Namen von Nutzern in der Google Workspace-Domain auf Workspace-Nutzerdaten zuzugreifen. Beispiel: Eine Anwendung, die die Google Calendar API verwendet, um den Kalendern aller Nutzer in einer Google Workspace-Domain Termine hinzuzufügen, 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.

Zum Delegieren domainweiter Befugnisse an ein Dienstkonto muss ein Super Admin der Google Workspace-Domain die folgenden Schritte ausführen:

  1. Gehen Sie in der Admin-Konsole Ihrer Google Workspace-Domain zu 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 in das Feld Client-ID die Client-ID des Dienstkontos ein. Sie finden die Client-ID Ihres Dienstkontos 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 erhalten soll. Wenn Ihre Anwendung beispielsweise domainweiten Vollzugriff auf die Google Drive API und die Google Calendar API benötigt, geben Sie https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar ein.
  6. Klicken Sie auf Authorize (Autorisieren).

Ihre Anwendung ist jetzt berechtigt, API-Aufrufe als Nutzer in Ihrer Workspace-Domain auszuführen (um die Identität von Nutzern zu übernehmen). Wenn Sie diese delegierten API-Aufrufe ausführen, geben Sie explizit den Nutzer an, der die Identität übernehmen soll.

Delegierten API-Aufruf vorbereiten

Java

Nachdem Sie die Client-E-Mail-Adresse und den privaten Schlüssel von API Consoleabgerufen haben, verwenden Sie die Google APIs-Clientbibliothek für Java, um ein GoogleCredential-Objekt aus den Anmeldedaten des Dienstkontos und den Bereichen zu erstellen, auf die Ihre Anwendung Zugriff benötigt. 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 App auf der Google Cloud Platform entwickeln, können Sie stattdessen die Standardanmeldedaten für Anwendungen verwenden, was den Prozess vereinfachen kann.

Domainweite Befugnisse delegieren

Wenn Sie den 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 Objekts GoogleCredential an. Beispiel:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

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

Python

Nachdem Sie die E-Mail-Adresse des Clients und den privaten Schlüssel von API Consoleabgerufen haben, verwenden Sie die Google APIs-Clientbibliothek für Python, um die folgenden Schritte auszuführen:

  1. Erstellen Sie aus den Anmeldedaten des Dienstkontos und den Bereichen, auf die Ihre Anwendung Zugriff benötigt, ein Credentials-Objekt. 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 App auf der Google Cloud Platform entwickeln, können Sie stattdessen die Standardanmeldedaten für Anwendungen verwenden, was den Prozess vereinfachen kann.

  2. Domainweite Befugnisse delegieren

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

    delegated_credentials = credentials.with_subject('user@example.org')

Verwenden Sie das Objekt „Anmeldedaten“, um Google APIs in Ihrer Anwendung aufzurufen.

HTTP/REST

Nachdem Sie die Client-ID und den privaten Schlüssel von API Consoleabgerufen haben, muss Ihre 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-Autorisierungsserver an.
  3. Verarbeiten Sie die JSON-Antwort, die der Autorisierungsserver zurückgibt.

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

Wenn die Antwort ein Zugriffstoken enthält, können Sie dieses zum Aufrufen einer Google API verwenden. Wenn die Antwort kein Zugriffstoken enthält, ist die JWT- und Tokenanfrage möglicherweise nicht richtig formuliert oder das Dienstkonto ist nicht berechtigt, auf die angeforderten Bereiche zuzugreifen.

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

Deine Serveranwendung fordert mithilfe eines JWT ein Token vom Google Authorization Server an und ruft dann mit dem Token einen Google API-Endpunkt auf. Endnutzer sind nicht beteiligt.

Im weiteren Verlauf dieses Abschnitts werden Details zum Erstellen eines JWT, zum Signieren des JWT, zum Formulieren der Zugriffstokenanfrage und zum Verarbeiten der Antwort beschrieben.

JWT erstellen

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

Ein JWT setzt sich so zusammen:

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

Der Basisstring für die Signatur lautet:

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

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

Dienstkonten basieren auf dem RSA-SHA-256-Algorithmus und dem JWT-Token-Format. Daher sieht die JSON-Darstellung des Headers so aus:

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

Die base64url-Darstellung sieht so aus:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
JWT-Anforderungssatz bilden

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

Erforderliche Ansprüche

Die erforderlichen Anforderungen im JWT-Anforderungssatz sind unten aufgeführt. Sie können in beliebiger Reihenfolge im Anspruchssatz vorkommen.

Name Beschreibung
iss Die E-Mail-Adresse des Dienstkontos.
scope Eine durch Leerzeichen getrennte Liste der Berechtigungen, die von der Anwendung angefordert werden.
aud Ein Bezeichner des beabsichtigten Ziels der Assertion. Wenn Sie eine Zugriffstokenanfrage stellen, ist dieser Wert immer https://oauth2.googleapis.com/token.
exp Die Ablaufzeit der Assertion, angegeben in Sekunden seit 00:00:00 UTC, 1. Januar 1970. Dieser Wert darf maximal eine Stunde nach der Ausstellungszeit liegen.
iat Der Zeitpunkt, zu dem die Assertion ausgeführt wurde, angegeben in Sekunden seit 00:00:00 UTC, 1. Januar 1970.

Im Folgenden sehen Sie die 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
}
Zusätzliche Ansprüche

In einigen Unternehmen kann eine Anwendung die domainweite Delegierung nutzen, um im Namen eines bestimmten Nutzers in einer Organisation zu handeln. Die Berechtigung für diese Art der Identitätsübernahme muss erteilt werden, bevor eine Anwendung die Identität eines Nutzers übernehmen kann. In der Regel wird dies von einem Super Admin verwaltet. Weitere Informationen finden Sie unter API-Zugriff mit domainweiter Delegierung verwalten.

Wenn Sie ein Zugriffstoken abrufen möchten, das einer Anwendung delegierten Zugriff auf eine Ressource gewährt, fügen Sie die E-Mail-Adresse des Nutzers in die JWT-Anforderung als Wert des Felds sub ein.

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

Wenn eine Anwendung nicht berechtigt ist, die Identität eines Nutzers zu übernehmen, wird als Antwort auf eine Zugriffstokenanfrage, die das Feld sub enthält, ein Fehler zurückgegeben.

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

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "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 UTF-8 serialisiert und base64url-sicher codiert sein. Im Folgenden finden 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-Websignatur (JWS) ist die Spezifikation, die den Mechanismus zum Generieren der Signatur für das JWT leitet. 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 beim Berechnen der Signatur verwendet werden. Der einzige Signaturalgorithmus, der vom Google OAuth 2.0 Authorization Server unterstützt wird, 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 mithilfe von SHA256withRSA (auch bekannt als RSASSA-PKCS1-V1_5-SIGN mit der SHA-256-Hash-Funktion) mit dem privaten Schlüssel, der von Google API Consoleabgerufen wird. 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. Folgende Angaben sind erforderlich (zur Verdeutlichung wurden Zeilenumbrüche hinzugefügt):

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

Hier 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 JWT, das signiert wurde und für die Ü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 Zugriffstoken-Anfrage ist eine HTTPS-POST-Anfrage und der Text ist URL-codiert. Die URL lautet wie folgt:

https://oauth2.googleapis.com/token

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

Name Beschreibung
grant_type Verwende den folgenden String (je nach Bedarf URL-codiert): urn:ietf:params:oauth:grant-type:jwt-bearer
assertion Das JWT, einschließlich Signatur.

Nachfolgend siehst du einen Rohdump der HTTPS-Anfrage POST, 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 sehen Sie dieselbe Anfrage mit curl:

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

Antwort verarbeiten

Wenn die JWT- und Zugriffstoken-Anfrage korrekt formuliert sind und das Dienstkonto die Berechtigung zum Ausführen des Vorgangs hat, enthält die JSON-Antwort vom Autorisierungsserver ein Zugriffstoken. Hier ist eine Beispielantwort:

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

Zugriffstokens können innerhalb des durch den Wert expires_in angegebenen Dauerfensters wiederverwendet werden.

Google APIs aufrufen

Java

Verwenden Sie das Objekt GoogleCredential, um Google APIs aufzurufen. Führen Sie dazu die folgenden Schritte aus:

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

Python

Verwenden Sie das autorisierte Objekt Credentials, um Google APIs aufzurufen. Führen Sie dazu die folgenden Schritte aus:

  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 Administration API auf:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Über die vom Dienstobjekt bereitgestellte Schnittstelle Anfragen an den API-Dienst stellen So listen Sie beispielsweise die Instanzen von Cloud SQL-Datenbanken im Projekt spannende-beispiel-123 auf:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

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

Sie können alle Google APIs testen und deren Bereiche im OAuth 2.0 Playground ansehen.

HTTP GET-Beispiele

Ein Aufruf des Endpunkts drive.files (die Drive Files API) mit dem HTTP-Header Authorization: Bearer könnte so aussehen. Sie müssen ein 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 curl-Befehlszeilenanwendung testen. Hier ist ein Beispiel, in dem die HTTP-Header-Option (bevorzugt) verwendet wird:

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

Alternativ können Sie folgende Parameteroption für den Abfragestring verwenden:

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

Wann Zugriffstokens ablaufen

Zugriffstokens, die vom Google OAuth 2.0-Autorisierungsserver ausgestellt werden, laufen nach dem mit dem Wert expires_in angegebenen Zeitraum ab. Wenn ein Zugriffstoken abläuft, sollte die Anwendung ein weiteres JWT generieren, 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 Delegierung zu verwenden, ist das Dienstkonto in der Admin-Konsole der Domain des Nutzers nicht autorisiert.

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

In der Regel dauert es einige Minuten, aber es kann bis zu 24 Stunden dauern, bis die Autorisierung für alle Nutzer in deinem Google-Konto wirksam 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 Client-E-Mail-Adresse anstelle der (numerischen) Client-ID autorisiert. Entfernen Sie in der Admin-Konsole auf der Seite Domainweite Delegierung den Client und fügen Sie ihn mit der numerischen ID noch einmal hinzu.
access_denied (beliebiger Wert) Wenn Sie die domainweite Delegierung verwenden, ist ein oder mehrere angeforderte Bereiche in der Admin-Konsole nicht autorisiert.

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

In der Regel dauert es einige Minuten, aber es kann bis zu 24 Stunden dauern, bis die Autorisierung für alle Nutzer in deinem Google-Konto wirksam wird.

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

Im Hilfeartikel Zugriff externer und interner Apps auf Google Workspace-Daten steuern finden Sie weitere Informationen dazu, wie ein Administrator den Zugriff auf alle oder vertrauliche und eingeschränkte Bereiche einschränken kann, bis der OAuth-Client-ID explizit Zugriff gewährt wird.

invalid_client (beliebiger Wert)

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

Weitere Informationen finden Sie in der Fehlerbeschreibung.

Achte darauf, dass das JWT-Token gültig ist und korrekte Anforderungen enthält.

Prüfen Sie, ob der OAuth-Client und das Dienstkonto richtig konfiguriert sind und 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üfe, ob die E-Mail-Adresse im sub-Anspruch (Feld) 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.

Normalerweise bedeutet dies, dass die lokale Systemzeit nicht korrekt ist. Der Fehler kann auch auftreten, wenn der exp-Wert mehr als 65 Minuten in der Zukunft vom iat-Wert entfernt ist oder der exp-Wert kleiner als iat ist.

Achte darauf, dass die Uhr des Systems, auf dem das JWT generiert wird, korrekt ist. Synchronisieren Sie Ihre Zeit bei Bedarf mit Google NTP.

invalid_grant Invalid JWT Signature.

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

Möglicherweise ist die JWT-Assertion auch falsch codiert – sie muss Base64-codiert sein und darf keine Zeilenumbrüche oder Gleichheitszeichen enthalten.

Decodieren Sie den JWT-Anforderungssatz und prüfen Sie, ob der Schlüssel, mit dem die Assertion signiert wurde, mit dem Dienstkonto verknüpft ist.

Verwende 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 von Bereichen) oder einer der angeforderten Bereiche ist nicht vorhanden (d.h. ungültig).

Prüfen Sie, ob die scope-Anforderung (Feld) des JWT ausgefüllt ist, und vergleichen Sie die darin enthaltenen Bereiche mit den dokumentierten Bereichen für die zu verwendenden APIs, um sicherzustellen, dass keine Fehler oder Tippfehler vorliegen.

Die Liste der Bereiche in der scope-Anforderung muss durch Leerzeichen und nicht durch Kommas getrennt werden.

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

Wechseln Sie zu Google API Consoleund aktivieren Sie unter IAM und Verwaltung > Dienstkonten das Dienstkonto, das die Schlüssel-ID zum Signieren der Assertion enthält.

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 zur Authentifizierung ein Dienstkonto der Organisation. Bestätigen Sie die Nutzertypkonfiguration für Ihre OAuth-Anwendung.

Zusatz: Dienstkontoautorisierung ohne OAuth

Bei einigen Google APIs können Sie autorisierte API-Aufrufe mit einem signierten JWT direkt als Inhabertoken statt mit einem OAuth 2.0-Zugriffstoken ausführen. Wenn dies möglich ist, musst du vor einem API-Aufruf keine Netzwerkanfrage an den Autorisierungsserver von Google senden.

Wenn für die API, die Sie aufrufen möchten, eine Dienstdefinition im GitHub-Repository für 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 mithilfe einer Standard-JWT-Bibliothek, z. B. einer Bibliothek unter jwt.io, ein JWT mit einem Header und einer Nutzlast wie im folgenden Beispiel:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • Geben Sie für das Feld kid im Header 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 im Feld aud den API-Endpunkt an. Beispiel: https://SERVICE.googleapis.com/.
    • Geben Sie im Feld iat die aktuelle Unix-Zeit und im Feld exp den Zeitpunkt genau 3.600 Sekunden später an, an dem das JWT abläuft.

Signiere das JWT mit RSA-256. Verwende dazu den privaten Schlüssel aus der JSON-Datei deines 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("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .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': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           '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 Inhabertoken auf:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com