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. Ein solches Konto ist einer Anwendung zugeordnet und nicht 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 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 ihren eigenen Daten und nicht mit den Daten eines Nutzers zu arbeiten. Eine Anwendung, die Google Cloud Datastore für die Datenpersistenz 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 erteilen, um im Namen von Nutzern in der Domain auf Nutzerdaten zuzugreifen.

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

Übersicht

Zur Unterstützung von Server-zu-Server-Interaktionen müssen Sie zuerst ein Dienstkonto für Ihr Projekt in der API Consoleerstellen. 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 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 mit dem Zugriffstoken Google APIs aufrufen.

Dienstkonto erstellen

Die Anmeldedaten eines Dienstkontos enthalten eine generierte E‑Mail-Adresse, die eindeutig ist, 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 Google App Engine ausgeführt wird, wird beim Erstellen des Projekts automatisch ein Dienstkonto eingerichtet.

Wenn Ihre Anwendung auf 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 Zugriff benötigt, 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 Google App Engine oder Google Compute Engine ausgeführt wird, müssen Sie diese Anmeldedaten im Google API Consoleabrufen. So generieren Sie Dienstkontoanmeldedaten oder rufen die öffentlichen Anmeldedaten auf, die Sie bereits generiert haben:

First, create a service account:

  1. Open the Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Click  Create service account.
  4. Under Service account details, type a name, ID, and description for the service account, then click Create and continue.
  5. Optional: Under Grant this service account access to project, select the IAM roles to grant to the service account.
  6. Click Continue.
  7. Optional: Under Grant users access to this service account, add the users or groups that are allowed to use and manage the service account.
  8. Click Done.

Next, create a service account key:

  1. Click the email address for the service account you created.
  2. Click the Keys tab.
  3. In the Add key drop-down list, select Create new key.
  4. Click Create.

Your new public/private key pair is generated and downloaded to your machine; it serves as the only copy of the private key. You are responsible for storing it securely. If you lose this key pair, you will need to generate a new one.

Sie können jederzeit zur API Console zurückkehren, um die E-Mail-Adresse, die Fingerabdrücke des öffentlichen Schlüssels und andere Informationen aufzurufen oder zusätzliche Paare aus öffentlichem/privatem Schlüssel 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 Datei mit dem privaten Schlüssel des Dienstkontos an einem Ort, auf den Ihre Anwendung zugreifen kann. Ihre Anwendung benötigt sie für autorisierte API-Aufrufe.

Domainweite Befugnisse an das Dienstkonto delegieren

Mit einem 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.

Damit einem Dienstkonto domainweite Berechtigungen erteilt werden können, muss ein Super-Admin der Google Workspace-Domain die folgenden Schritte ausführen:

  1. Rufen Sie in der Admin-Konsole Ihrer Google Workspace-Domain das Hauptmenü  > „Sicherheit“ > „Zugriffs- und Datenkontrolle“ > „API-Steuerung“ auf.
  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 erhalten soll. Wenn Ihre Anwendung beispielsweise domainweiten Vollzugriff 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 hat jetzt die Berechtigung, API-Aufrufe als Nutzer in Ihrer Workspace-Domain zu senden (um Nutzer zu „imitieren“). Wenn Sie diese delegierten API-Aufrufe vorbereiten, geben Sie den Nutzer an, dessen Identität angenommen werden soll.

Vorbereiten eines delegierten API-Aufrufs

Java

Nachdem Sie die Client-E-Mail-Adresse und den privaten Schlüssel aus API Consoleabgerufen haben, verwenden Sie die Google Auth Library for Java, um ein GoogleCredentials-Objekt aus den Anmeldedaten des Dienstkontos und den Bereichen zu erstellen, auf die Ihre Anwendung Zugriff benötigt. Beispiel:

import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

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

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

Domainweite Befugnisse delegieren

Wenn Sie dem Dienstkonto domainweiten Zugriff 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 GoogleCredentials an. Beispiel:

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

Im obigen Code wird das GoogleCredentials-Objekt verwendet, um die Methode createDelegated() aufzurufen. Das Argument für die createDelegated()-Methode muss ein Nutzer sein, der zu Ihrem Workspace-Konto gehört. Mit diesen Anmeldedaten wird in Ihrem Code, der die Anfrage stellt, Google APIs über Ihr Dienstkonto aufgerufen.

Python

Nachdem Sie die Client-E-Mail-Adresse und den privaten Schlüssel aus API Consoleabgerufen haben, führen Sie die folgenden Schritte mit der Google APIs-Clientbibliothek für Python 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 Platform entwickeln, können Sie stattdessen die Standardanmeldedaten für Anwendungen verwenden. Dies vereinfacht den Vorgang.

  2. Domainweite Befugnisse delegieren

    Wenn Sie dem Dienstkonto domainweiten Zugriff 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 Credentials-Objekt, um Google APIs in Ihrer Anwendung aufzurufen.

HTTP/REST

Nachdem Sie die Client-ID und den privaten Schlüssel von der API Consoleerhalten 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 es zum Aufrufen einer Google API verwenden. Wenn die Antwort kein Zugriffstoken enthält, sind Ihr JWT und Ihre Tokenanfrage möglicherweise nicht richtig formatiert oder das Dienstkonto hat keine Berechtigung für den 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 Google-Autorisierungsserver anzufordern. Anschließend wird das Token verwendet, um einen Google-API-Endpunkt aufzurufen. Es ist kein Endnutzer beteiligt.

Im Rest dieses Abschnitts wird beschrieben, wie Sie ein JWT erstellen, das JWT signieren, die Zugriffstokenanfrage erstellen und die Antwort verarbeiten.

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 Base64url-Codierung codiert. Diese Codierung bietet Schutz vor Codierungsänderungen aufgrund wiederholter Codierungsvorgänge. Der Header, der Anforderungssatz und die Signatur werden mit einem Punkt (.) verkettet.

Ein JWT besteht aus folgenden Teilen:

{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 erstellen

Der Header besteht aus zwei Pflichtfeldern: dem Signaturalgorithmus und dem Format der Assertion sowie einer optionalen Schlüssel-ID:

  • Der Algorithmus ist obligatorisch und hat nur einen Wert: "alg": "RS256".
  • Das Format ist obligatorisch und hat nur einen Wert: "typ": "JWT".
  • Die Schlüssel-ID ist optional und ist die ID des Dienstkontoschlüssels, der zum Signieren des JWT verwendet wird. Wenn eine falsche Schlüssel-ID angegeben wird, werden alle Schlüssel, die dem Dienstkonto zugeordnet sind, ausprobiert. Wenn kein gültiger Schlüssel gefunden wird, wird das Token abgelehnt. Google behält sich das Recht vor, Tokens mit falschen Schlüssel-IDs 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 davon ist:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
JWT-Anforderungssatz erstellen

Der JWT-Anforderungssatz enthält Informationen zum JWT, einschließlich der angeforderten Berechtigungen (Bereich), 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 Ein Deskriptor des beabsichtigten Ziels der Assertion. Wenn Sie ein Zugriffstoken anfordern, ist dieser Wert immer https://oauth2.googleapis.com/token.
exp Die Ablaufzeit der Assertion, angegeben in Sekunden seit dem 1. Januar 1970 um 00:00:00 UTC. Dieser Wert darf maximal 1 Stunde nach der Ausstellungszeit liegen.
iat Die Zeit, zu der die Assertion ausgestellt 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
}
Zusätzliche Ansprüche

In einigen Unternehmensanwendungsfällen kann eine Anwendung die domänenweite Delegation verwenden, um im Namen eines bestimmten Nutzers in einer Organisation zu agieren. Die Berechtigung für diese Art von Identitätswechsel muss erteilt werden, bevor eine Anwendung die Identität eines Nutzers annehmen kann. Dies wird in der Regel von einem Super Admin erledigt. Weitere Informationen finden Sie unter Zugriff auf die API mit domainweiter Delegierung verwalten.

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

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

Wenn eine Anwendung keine Berechtigung hat, die Identität eines Nutzers anzunehmen, ist die Antwort auf eine Zugriffstokenanfrage, die das Feld sub enthält, ein Fehler.

Unten sehen Sie 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 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 Spezifikation JSON Web Signature (JWS) 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 beim Berechnen der Signatur verwendet werden. Der einzige Signaturalgorithmus, der vom Google OAuth 2.0-Autorisierungsserver unterstützt wird, ist RSA mit dem SHA-256-Hashing-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 von Google API Consoleabgerufen wurde. Die Ausgabe ist ein Byte-Array.

Die Signatur muss dann Base64url-codiert werden. Der Header, der Anforderungssatz und die Signatur werden mit einem Punktzeichen (.) verkettet. Das Ergebnis ist das JWT. Es sollte so aussehen (Zeilenumbrüche zur besseren Lesbarkeit):

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

Das folgende Beispiel zeigt 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 wird unten angezeigt:

https://oauth2.googleapis.com/token

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

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

Unten sehen Sie 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 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 das JWT und die Zugriffstokenanfrage korrekt formatiert sind und das Dienstkonto die Berechtigung hat, den Vorgang auszuführen, 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 expires_in-Wert angegebenen Zeitfensters wiederverwendet werden.

Google APIs aufrufen

Java

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

  1. Erstellen Sie mit dem GoogleCredentials-Objekt ein Dienstobjekt für die API, die Sie aufrufen möchten. Beispiel:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credentials).build();
  2. Stellen Sie Anfragen an den API-Dienst über die vom Dienstobjekt bereitgestellte Schnittstelle. 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

So rufen Sie Google-APIs mit dem autorisierten Credentials-Objekt auf:

  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 sowie 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. Stellen Sie Anfragen an den API-Dienst über die vom Dienstobjekt bereitgestellte Schnittstelle. 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 das Token verwenden, um im Namen eines bestimmten Dienstkontos oder Nutzerkontos Aufrufe an eine Google-API zu senden, sofern die von der API erforderlichen Zugriffsbereiche gewährt wurden. Dazu müssen Sie das Zugriffstoken in eine Anfrage an die API einfügen. Verwenden Sie dazu entweder den Abfrageparameter access_token oder den HTTP-Header Authorization mit dem Wert Bearer. Wenn möglich, ist der HTTP-Header vorzuziehen, da Abfragestrings in der Regel in Serverlogs sichtbar sind. In den meisten Fällen können Sie eine Clientbibliothek verwenden, um Ihre Aufrufe von Google APIs einzurichten, z. B. beim Aufrufen der Drive Files API.

Sie können alle Google APIs und ihre Bereiche im OAuth 2.0 Playground ausprobieren.

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 Query-String-Parameter 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 ein Beispiel mit der HTTP-Header-Option (bevorzugt):

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

Alternativ können Sie auch die Option für den Abfragestringparameter verwenden:

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

Ablauf von Zugriffstokens

Zugriffstokens, die vom Google OAuth 2.0-Autorisierungsserver ausgestellt werden, laufen nach der Dauer ab, die durch den Wert expires_in angegeben wird. 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 Problemlösung
unauthorized_client Unauthorized client or scope in request. Wenn Sie die domainweite Delegation verwenden möchten, ist das Dienstkonto nicht in der Admin-Konsole der Domain des Nutzers autorisiert.

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

Das dauert in der Regel einige Minuten, kann aber auch bis zu 24 Stunden in Anspruch nehmen.

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 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 einer der angeforderten Bereiche nicht in der Admin-Konsole autorisiert.

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

Das dauert in der Regel einige Minuten, kann aber auch bis zu 24 Stunden in Anspruch nehmen.

admin_policy_enforced (beliebiger Wert) Das Google-Konto kann aufgrund der Richtlinien des Google Workspace-Administrators nicht für einen oder mehrere angeforderte Bereiche autorisiert werden.

Weitere Informationen dazu, wie ein Administrator den Zugriff auf alle Bereiche oder auf vertrauliche und eingeschränkte Bereiche einschränken kann, bis der Zugriff explizit für Ihre OAuth-Client-ID 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.

Achten Sie darauf, dass das JWT-Token gültig ist und die richtigen Anforderungen 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üfen Sie, ob das JWT-Token korrekt ist und für die Client-ID in der Anfrage ausgestellt wurde.

deleted_client (beliebiger Wert)

Der OAuth-Client, der für die Anfrage verwendet wird, wurde gelöscht. Das Löschen kann manuell oder automatisch erfolgen, wenn nicht verwendete Clients vorhanden sind. Gelöschte Mandanten können innerhalb von 30 Tagen nach dem Löschen wiederhergestellt werden. Weitere Informationen

Verwenden Sie eine Client-ID, die noch aktiv ist.

invalid_grant Not a valid email. Der Nutzer ist nicht vorhanden. Prüfen Sie, ob die E-Mail-Adresse in der sub-Anforderung (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.

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 des iat-Werts liegt oder der exp-Wert niedriger als der iat-Wert ist.

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

invalid_grant Invalid JWT Signature.

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

Alternativ kann die JWT-Assertion falsch codiert sein. Sie muss Base64-codiert sein und darf keine Zeilenumbrüche oder Füllzeichen enthalten.

Decodieren Sie die JWT-Anforderungen und prüfen Sie, ob der Schlüssel, mit dem die Assertion signiert wurde, dem Dienstkonto zugeordnet 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 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 APIs, die Sie verwenden möchten, um Fehler oder Tippfehler auszuschließen.

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 wurde, ist deaktiviert.

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

org_internal This client is restricted to users within its organization. Die OAuth-Client-ID in der Anfrage gehört zu einem Projekt, das den Zugriff auf Google-Konten in einer bestimmten Google Cloud-Organisation einschränkt.

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

Anhang: Dienstkontoautorisierung 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 durchführen. Wenn dies möglich ist, können Sie vermeiden, eine Netzwerkanfrage an den Autorisierungsserver von Google zu senden, bevor Sie einen API-Aufruf durchführen.

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

  1. Erstellen Sie ein Dienstkonto wie oben beschrieben. Bewahren Sie die JSON-Datei auf, die Sie beim Erstellen des Kontos erhalten.
  2. Erstellen Sie 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": "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 Ihrer JSON-Datei für das Dienstkonto.
    • Geben Sie für die Felder iss und sub die E-Mail-Adresse Ihres Dienstkontos an. Sie finden diesen Wert im Feld client_email Ihrer JSON-Datei für das Dienstkonto.
    • 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 genau 3.600 Sekunden später an, wenn das JWT abläuft.

Signieren Sie das JWT mit RSA-256 mithilfe des privaten Schlüssels in der JSON-Datei Ihres Dienstkontos.

Beispiel:

Java

google-auth-library-java und java-jwt verwenden:

import com.google.auth.oauth2.ServiceAccountCredentials;
...
GoogleCredentials credentials =
        GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = ((ServiceAccountCredentials) credentials).getPrivateKey();
String privateKeyId = ((ServiceAccountCredentials) credentials).getPrivateKeyId();

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 auf und verwenden Sie das signierte JWT als Bearer-Token:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

Produktübergreifenden Kontoschutz implementieren

Ein zusätzlicher Schritt, den Sie unternehmen sollten, um die Konten Ihrer Nutzer zu schützen, ist die Implementierung von Cross-Account Protection mithilfe des Cross-Account Protection Service von Google. Mit diesem Dienst können Sie Benachrichtigungen zu Sicherheitsereignissen abonnieren, die Ihre Anwendung über wichtige Änderungen am Nutzerkonto informieren. Anhand dieser Informationen können Sie dann Maßnahmen ergreifen, je nachdem, wie Sie auf Ereignisse reagieren möchten.

Hier einige Beispiele für die Ereignistypen, die vom Google Cross-Account Protection Service 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

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