Zu Google Identity Services migrieren

Übersicht

Google bietet mehrere JavaScript-Bibliotheken an, um ein Zugriffstoken pro Nutzer zum Aufrufen von Google APIs zu erhalten:

In dieser Anleitung wird beschrieben, wie Sie von diesen Bibliotheken zur Google Identity Services-Bibliothek migrieren.

Wenn Sie dieser Anleitung folgen, werden Sie:

  • Ersetzen Sie die eingestellte Plattformbibliothek durch die Identity Services-Bibliothek.
  • Wenn Sie die API-Clientbibliothek verwenden, entfernen Sie das eingestellte Modul gapi.auth2, seine Methoden und Objekte und ersetzen Sie sie durch die entsprechenden Identity Services-Elemente.

Eine Beschreibung der Änderungen an der Identity Services JavaScript-Bibliothek finden Sie in der Übersicht. Informationen zu wichtigen Begriffen und Konzepten finden Sie unter Funktionsweise der Nutzerautorisierung.

Wenn Sie die Authentifizierung für die Registrierung und Anmeldung von Nutzern benötigen, lesen Sie stattdessen den Abschnitt Von Google Log-in migrieren.

Autorisierungsablauf ermitteln

Es gibt zwei mögliche Nutzerautorisierungsabläufe: implizit und Autorisierungscode.

Überprüfen Sie Ihre Webanwendung, um den verwendeten Autorisierungsablauf zu ermitteln.

Hinweise darauf, dass Ihre Web-App den impliziten Ablauf verwendet:

  • Ihre Web-App basiert ausschließlich auf dem Browser und hat keine Backend-Plattform.
  • Der Nutzer muss anwesend sein, um Google-APIs aufzurufen. Ihre App verwendet nur Zugriffstokens und benötigt keine Aktualisierungstokens.
  • Ihre Web-App wird geladen apis.google.com/js/api.js.
  • Ihre Implementierung basiert auf OAuth 2.0 für clientseitige Webanwendungen.
  • Ihre App verwendet entweder die Module gapi.client oder gapi.auth2 aus der Google API-Clientbibliothek für JavaScript.

Hinweise darauf, dass Ihre Webanwendung den Autorisierungscode-Vorgang verwendet:

  • Ihre Implementierung basiert auf:

  • Ihre App wird sowohl im Browser des Nutzers als auch auf Ihrer Backend-Plattform ausgeführt.

  • Ihre Backend-Plattform hostet einen Autorisierungscode-Endpunkt.

  • Ihre Backend-Plattform ruft Google-APIs im Namen von Nutzern auf, ohne dass diese anwesend sein müssen. Dies wird auch als Offlinemodus bezeichnet.

  • Aktualisierungstokens werden von Ihrer Backend-Plattform verwaltet und gespeichert.

In einigen Fällen unterstützt Ihre Codebasis möglicherweise beide Abläufe.

Autorisierungsablauf auswählen

Bevor Sie mit der Migration beginnen, müssen Sie entscheiden, ob Sie Ihren bestehenden Ablauf beibehalten oder einen anderen Ablauf verwenden möchten.

Unter Autorisierungsablauf auswählen finden Sie Informationen zu den wichtigsten Unterschieden und Kompromissen zwischen den beiden Abläufen.

In den meisten Fällen wird der Autorisierungscode-Vorgang empfohlen, da er das höchste Maß an Nutzersicherheit bietet. Durch die Implementierung dieses Ablaufs kann Ihre Plattform auch neue Offlinefunktionen hinzufügen, z. B. das Abrufen von Updates, um Nutzer über wichtige Änderungen an ihrem Kalender, ihren Fotos und ihren Abos zu informieren.

Wählen Sie mithilfe der Auswahlfelder einen Autorisierungsablauf aus.

Impliziter Ablauf

Zugriffstoken für die Verwendung im Browser abrufen, während der Nutzer anwesend ist

Unter Beispiele für den impliziten Ablauf sehen Sie Web-Apps vor und nach der Migration zu Identity Services.

Autorisierungscode-Ablauf

Ein von Google ausgestellter Autorisierungscode pro Nutzer wird an Ihre Backend-Plattform gesendet, wo er dann gegen ein Zugriffstoken und ein Aktualisierungstoken eingetauscht wird.

Unter Beispiele für den Autorisierungscode-Ablauf sehen Sie Web-Apps vor und nach der Migration zu Identity Services.

Folgen Sie in dieser Anleitung den fett gedruckten Anweisungen, um vorhandene Funktionen zu hinzuzufügen, entfernen, aktualisieren oder ersetzen.

Änderungen an Ihrer In-Browser-Web-App

In diesem Abschnitt werden die Änderungen beschrieben, die Sie an Ihrer In-Browser-Web-App vornehmen müssen, wenn Sie zur Google Identity Services-JavaScript-Bibliothek migrieren.

Betroffenen Code ermitteln und testen

Ein Debug-Cookie kann helfen, betroffenen Code zu finden und das Verhalten nach der Einstellung zu testen.

Bei großen oder komplexen Apps kann es schwierig sein, den gesamten Code zu finden, der von der Einstellung des gapi.auth2-Moduls betroffen ist. Wenn Sie die vorhandene Verwendung von Funktionen, die bald eingestellt werden, in der Konsole protokollieren möchten, legen Sie den Wert des Cookies G_AUTH2_MIGRATION auf informational fest. Optional können Sie einen Doppelpunkt gefolgt von einem Schlüsselwert hinzufügen, um auch im Sitzungsspeicher zu protokollieren. Nach der Anmeldung und dem Empfang von Anmeldedaten werden die erfassten Protokolle zur späteren Analyse an ein Backend gesendet. Mit informational:showauth2use werden beispielsweise der Ursprung und die URL in einem Sitzungsspeicherschlüssel mit dem Namen showauth2use gespeichert.

Wenn Sie das Verhalten der App prüfen möchten, wenn das gapi.auth2-Modul nicht mehr geladen wird, legen Sie den Wert des G_AUTH2_MIGRATION-Cookies auf enforced fest. So können Sie das Verhalten nach der Einstellung vor dem Datum der Erzwingung testen.

Mögliche G_AUTH2_MIGRATION-Cookie-Werte:

  • enforced Das Modul gapi.auth2 wird nicht geladen.
  • informational Verwendung eingestellter Funktionen in der JS-Konsole protokollieren. Außerdem wird im Sitzungsspeicher protokolliert, wenn ein optionaler Schlüsselname festgelegt ist: informational:key-name.

Um die Auswirkungen auf Nutzer zu minimieren, empfehlen wir, dieses Cookie zuerst lokal während der Entwicklung und des Tests festzulegen, bevor Sie es in Produktionsumgebungen verwenden.

Bibliotheken und Module

Das gapi.auth2-Modul verwaltet die Nutzerauthentifizierung für die Anmeldung und den impliziten Ablauf für die Autorisierung. Ersetzen Sie dieses eingestellte Modul sowie seine Objekte und Methoden durch die Google Identity Services-Bibliothek.

Fügen Sie die Identity Services-Bibliothek Ihrer Web-App hinzu, indem Sie sie in Ihr Dokument einfügen:

<script src="https://accounts.google.com/gsi/client" async defer></script>

Entfernen Sie alle Instanzen des Ladens des auth2-Moduls mit gapi.load('auth2', function).

Die Google Identity Services-Bibliothek ersetzt die Verwendung des gapi.auth2-Moduls. Sie können das gapi.client-Modul aus der Google API Client Library for JavaScript weiterhin verwenden und die automatische Erstellung aufrufbarer JS-Methoden aus einem Discovery-Dokument, das Batching mehrerer API-Aufrufe und die CORS-Verwaltungsfunktionen nutzen.

Kekse

Für die Nutzerautorisierung ist die Verwendung von Cookies nicht erforderlich.

Weitere Informationen dazu, wie bei der Nutzerauthentifizierung Cookies verwendet werden, finden Sie unter Von Google Log-in migrieren. Informationen zur Verwendung von Cookies durch andere Google-Produkte und ‑Dienste finden Sie unter Wie Google Cookies verwendet.

Anmeldedaten

Bei Google Identity Services werden Nutzerauthentifizierung und ‑autorisierung in zwei separate Vorgänge unterteilt und Nutzeranmeldedaten sind getrennt: Das ID-Token, das zur Identifizierung eines Nutzers verwendet wird, wird separat vom Zugriffstoken zurückgegeben, das zur Autorisierung verwendet wird.

Beispielanmeldedaten

Impliziter Ablauf

Trennen Sie die Nutzerauthentifizierung und ‑autorisierung, indem Sie die Verarbeitung von Nutzerprofilen aus Autorisierungsabläufen entfernen.

Entfernen Sie diese Referenzen zum Google Log-in-JavaScript-Client:

Methoden

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

Autorisierungscode-Ablauf

Identity Services trennt Anmeldedaten im Browser in ID-Token und Zugriffstoken. Diese Änderung gilt nicht für Anmeldedaten, die durch direkte Aufrufe von Google OAuth 2.0-Endpunkten von Ihrer Backend-Plattform oder über Bibliotheken, die auf einem sicheren Server auf Ihrer Plattform ausgeführt werden, wie z. B. den Google APIs Node.js Client, abgerufen werden.

Sitzungsstatus

Bisher konnten Sie mit Google Log-in den Anmeldestatus von Nutzern so verwalten:

Sie sind für die Verwaltung des Anmeldestatus und der Nutzersitzungen für Ihre Web-App verantwortlich.

Entfernen Sie diese Referenzen zum Google Log-in-JavaScript-Client:

Objekte:

  • gapi.auth2.SignInOptions

Methoden:

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

Clientkonfiguration

Aktualisieren Sie Ihre Web-App, um einen Token-Client für den impliziten oder Autorisierungscode-Ablauf zu initialisieren.

Entfernen Sie diese Referenzen zum Google Log-in-JavaScript-Client:

Objekte:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

Methoden:

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

Impliziter Ablauf

Fügen Sie ein TokenClientConfig-Objekt und einen initTokenClient()-Aufruf hinzu, um Ihre Web-App zu konfigurieren. Folgen Sie dabei dem Beispiel unter Token-Client initialisieren.

Ersetzen Sie Google Log-in-JavaScript-Clientreferenzen durch Google Identity Services:

Objekte:

  • gapi.auth2.AuthorizeConfig mit TokenClientConfig

Methoden:

  • gapi.auth2.init() mit google.accounts.oauth2.initTokenClient()

Parameter:

  • gapi.auth2.AuthorizeConfig.login_hint mit TokenClientConfig.login_hint.
  • gapi.auth2.GoogleUser.getHostedDomain() mit TokenClientConfig.hd.

Autorisierungscode-Ablauf

Fügen Sie ein CodeClientConfig-Objekt und einen initCodeClient()-Aufruf hinzu, um Ihre Web-App zu konfigurieren. Folgen Sie dabei dem Beispiel unter Code-Client initialisieren.

Beim Wechsel vom impliziten zum Autorisierungscode-Ablauf gilt Folgendes:

Entfernen von Referenzen zum Google Log-in-JavaScript-Client

Objekte:

  • gapi.auth2.AuthorizeConfig

Methoden:

  • gapi.auth2.init()

Parameter:

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

Tokenanfrage

Durch eine Nutzeraktion, z. B. einen Klick auf eine Schaltfläche, wird eine Anfrage generiert, die dazu führt, dass ein Zugriffstoken direkt an den Browser des Nutzers zurückgegeben wird (beim impliziten Ablauf) oder an Ihre Backend-Plattform, nachdem ein Autorisierungscode pro Nutzer gegen ein Zugriffstoken und ein Aktualisierungstoken eingetauscht wurde.

Impliziter Ablauf

Zugriffstokens können im Browser abgerufen und verwendet werden, während der Nutzer angemeldet ist und eine aktive Sitzung mit Google hat. Im impliziten Modus ist eine Nutzeraktion erforderlich, um ein Zugriffstoken anzufordern, auch wenn zuvor eine Anfrage gestellt wurde.

Ersetzen Sie Referenzen zum Google Log-in-JavaScript-Client durch Google Identity Services:

Methoden:

  • gapi.auth2.authorize() mit TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() mit TokenClient.requestAccessToken()

Fügen Sie einen Link oder eine Schaltfläche hinzu, um requestAccessToken() aufzurufen und den Pop-up-UX-Ablauf zum Anfordern eines Zugriffstokens zu starten oder ein neues Token abzurufen, wenn das vorhandene Token abläuft.

Aktualisieren Sie Ihre Codebasis, damit Folgendes möglich ist:

  • OAuth 2.0-Tokenvorgang mit requestAccessToken() auslösen.
  • Unterstützen Sie die inkrementelle Autorisierung, indem Sie requestAccessToken und OverridableTokenClientConfig verwenden, um eine Anfrage für viele Bereiche in mehrere kleinere Anfragen aufzuteilen.
  • Fordern Sie ein neues Token an, wenn das vorhandene Token abläuft oder widerrufen wird.

Wenn Sie mit mehreren Bereichen arbeiten, sind möglicherweise strukturelle Änderungen an Ihrem Code erforderlich, um den Zugriff auf Bereiche nur bei Bedarf und nicht alle auf einmal anzufordern. Dies wird als inkrementelle Autorisierung bezeichnet. Jede Anfrage sollte so wenige Bereiche wie möglich und idealerweise nur einen Bereich enthalten. Weitere Informationen zum Umgang mit der Nutzereinwilligung

Wenn ein Zugriffstoken abläuft, ruft das gapi.auth2-Modul automatisch ein neues, gültiges Zugriffstoken für Ihre Web-App ab. Aus Gründen der Nutzersicherheit wird dieser automatische Token-Aktualisierungsprozess von der Google Identity Services-Bibliothek nicht unterstützt. Ihre Web-App muss aktualisiert werden, damit sie ein abgelaufenes Zugriffstoken erkennen und ein neues anfordern kann. Weitere Informationen finden Sie im Abschnitt „Token-Verarbeitung“.

Autorisierungscode-Ablauf

Fügen Sie einen Link oder eine Schaltfläche hinzu, um requestCode() aufzurufen und einen Autorisierungscode von Google anzufordern. Ein Beispiel finden Sie unter OAuth 2.0-Vorgang mit Autorisierungscode auslösen.

Weitere Informationen dazu, wie Sie auf ein abgelaufenes oder widerrufenes Zugriffstoken reagieren, finden Sie im Abschnitt zur Token-Verarbeitung.

Umgang mit Tokens

Fügen Sie eine Fehlerbehandlung hinzu, um fehlgeschlagene Google API-Aufrufe zu erkennen, wenn ein abgelaufenes oder widerrufenes Zugriffstoken verwendet wird, und um ein neues, gültiges Zugriffstoken anzufordern.

Ein HTTP-Statuscode von 401 Unauthorized und die Fehlermeldung invalid_token werden von Google-APIs zurückgegeben, wenn ein abgelaufenes oder widerrufenes Zugriffstoken verwendet wird. Ein Beispiel finden Sie unter Antwort mit ungültigem Token.

Abgelaufene Tokens

Zugriffstokens sind kurzlebig und oft nur wenige Minuten gültig.

Tokenwiderruf

Der Inhaber eines Google-Kontos kann eine zuvor erteilte Einwilligung jederzeit widerrufen. Dadurch werden vorhandene Zugriffs- und Aktualisierungstokens ungültig. Der Widerruf kann über Ihre Plattform mit revoke() oder über ein Google-Konto ausgelöst werden.

Ersetzen Sie Referenzen zum Google Log-in-JavaScript-Client durch Google Identity Services:

Methoden:

  • getAuthInstance().disconnect() mit google.accounts.oauth2.revoke()
  • GoogleUser.disconnect() mit google.accounts.oauth2.revoke()

Rufen Sie revoke auf, wenn ein Nutzer sein Konto auf Ihrer Plattform löscht oder die Einwilligung zum Teilen von Daten mit Ihrer App widerrufen möchte.

Google zeigt dem Nutzer ein Zustimmungsdialogfeld an, wenn entweder Ihre Web-App oder Ihre Backend-Plattform ein Zugriffstoken anfordert. Beispiel für Zustimmungsdialogfelder, die Nutzern von Google angezeigt werden

Bevor ein Zugriffstoken für Ihre App ausgestellt wird, ist eine bestehende und aktive Google-Sitzung erforderlich, um die Zustimmung des Nutzers einzuholen und das Ergebnis aufzuzeichnen. Der Nutzer muss sich möglicherweise in einem Google-Konto anmelden, wenn noch keine Sitzung vorhanden ist.

Nutzer anmelden

Nutzer können in einem separaten Browsertab oder nativ über einen Browser oder ein Betriebssystem in einem Google-Konto angemeldet sein. Wir empfehlen, Mit Google anmelden auf Ihrer Website hinzuzufügen, um eine aktive Sitzung zwischen einem Google-Konto und dem Browser herzustellen, wenn der Nutzer Ihre App zum ersten Mal öffnet. Das bietet folgende Vorteile:

  • Die Anzahl der Anmeldungen, die ein Nutzer durchführen muss, wird minimiert. Wenn ein Zugriffstoken angefordert wird, wird der Anmeldevorgang für das Google-Konto gestartet, falls noch keine aktive Sitzung vorhanden ist.
  • Verwenden Sie das Feld credential email des JWT-ID-Tokens direkt als Wert des Parameters login_hint in CodeClientConfig- oder TokenClientConfig-Objekten. Das ist besonders hilfreich, wenn Ihre Plattform kein System zur Verwaltung von Nutzerkonten hat.
  • Ein Google-Konto mit einem bestehenden lokalen Nutzerkonto auf Ihrer Plattform verknüpfen, um doppelte Konten auf Ihrer Plattform zu vermeiden.
  • Wenn ein neues lokales Konto erstellt wird, können Ihre Registrierungsdialogfelder und ‑abläufe klar von den Dialogfeldern und ‑abläufen für die Nutzerauthentifizierung getrennt werden. Dadurch wird die Anzahl der erforderlichen Schritte verringert und die Abbruchrate verbessert.

Nach der Anmeldung und bevor ein Zugriffstoken ausgestellt wird, müssen Nutzer Ihrer Anwendung die Einwilligung für die angeforderten Bereiche erteilen.

Nach der Einwilligung wird ein Zugriffstoken zusammen mit einer Liste der vom Nutzer genehmigten oder abgelehnten Bereichsanforderungen zurückgegeben.

Mit detaillierten Berechtigungen können Nutzer einzelne Bereiche genehmigen oder ablehnen. Wenn Sie Zugriff auf mehrere Bereiche anfordern, wird jeder Bereich unabhängig von den anderen Bereichen gewährt oder abgelehnt. Basierend auf der Auswahl des Nutzers werden in Ihrer App selektiv Funktionen und Features aktiviert, die von einem individuellen Bereich abhängen.

Impliziter Ablauf

Ersetzen Sie Google Log-in-JavaScript-Clientreferenzen durch Google Identity Services:

Objekte:

  • gapi.auth2.AuthorizeResponse mit TokenClient.TokenResponse
  • gapi.auth2.AuthResponse mit TokenClient.TokenResponse

Methoden:

  • GoogleUser.hasGrantedScopes() mit google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() mit google.accounts.oauth2.hasGrantedAllScopes()

Entfernen von Referenzen zum Google Log-in-JavaScript-Client:

Methoden:

  • GoogleUser.getAuthResponse()

Aktualisieren Sie Ihre Web-App mit hasGrantedAllScopes() und hasGrantedAnyScope(). Hier finden Sie ein Beispiel für detaillierte Berechtigungen.

Autorisierungscode-Ablauf

Aktualisieren oder Fügen Sie einen Autorisierungscode-Endpunkt zu Ihrer Backend-Plattform hinzu. Folgen Sie dazu der Anleitung unter Autorisierungscode-Verarbeitung.

Aktualisieren Sie Ihre Plattform gemäß der Anleitung unter Code-Modell verwenden, um die Anfrage zu validieren und ein Zugriffs- und Aktualisierungstoken zu erhalten.

Aktualisieren Sie Ihre Plattform, um Funktionen und Features basierend auf den einzelnen Bereichen, die der Nutzer genehmigt hat, selektiv zu aktivieren oder zu deaktivieren. Folgen Sie dazu der Anleitung für die inkrementelle Autorisierung und prüfen Sie die vom Nutzer gewährten Zugriffsbereiche.

Beispiele für implizite Vorgänge

Die alte Methode

GAPI-Clientbibliothek

Beispiel für die Google API-Clientbibliothek für JavaScript, die in einem Browser mit einem Pop-up-Dialogfeld für die Einwilligung des Nutzers ausgeführt wird.

Das gapi.auth2-Modul wird automatisch von gapi.client.init() geladen und verwendet und ist daher ausgeblendet.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

JS-Clientbibliothek

OAuth 2.0 für clientseitige Webanwendungen, die in einem Browser ausgeführt werden und ein Pop-up-Dialogfeld für die Einwilligung des Nutzers verwenden.

Das Modul gapi.auth2 wird manuell geladen.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from Google Cloud console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

OAuth 2.0-Endpunkte

OAuth 2.0 für clientseitige Webanwendungen, die im Browser ausgeführt werden und Weiterleitungen zu Google verwenden, um die Einwilligung des Nutzers einzuholen.

In diesem Beispiel werden direkte Aufrufe der OAuth 2.0-Endpunkte von Google über den Browser des Nutzers gezeigt. Das gapi.auth2-Modul oder eine JavaScript-Bibliothek werden nicht verwendet.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

Jetzt

Nur GIS

In diesem Beispiel wird nur die JavaScript-Bibliothek des Google Identity Service mit dem Tokenmodell und dem Pop-up-Dialog für die Nutzereinwilligung gezeigt. Es soll die Mindestanzahl der Schritte veranschaulichen, die zum Konfigurieren eines Clients, zum Anfordern und Abrufen eines Zugriffstokens und zum Aufrufen einer Google API erforderlich sind.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI-Async/Await

In diesem Beispiel wird gezeigt, wie Sie die Google Identity Services-Bibliothek mit dem Tokenmodell hinzufügen, das gapi.auth2-Modul entfernen und eine API mit der Google API-Clientbibliothek für JavaScript aufrufen.

Promises, async und await werden verwendet, um die Reihenfolge des Ladens der Bibliothek zu erzwingen und Autorisierungsfehler abzufangen und zu wiederholen. Ein API-Aufruf erfolgt erst, wenn ein gültiges Zugriffstoken verfügbar ist.

Nutzer müssen auf die Schaltfläche „Kalender anzeigen“ klicken, wenn das Zugriffstoken beim ersten Laden der Seite fehlt oder später, nachdem das Zugriffstoken abgelaufen ist.

<!DOCTYPE html>
<html>
<head>
    <title>GAPI and GIS Example</title>
    <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
    <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoad()"></script>
</head>
<body>
    <h1>GAPI Client with GIS Authorization</h1>
    <button id="authorizeBtn" style="visibility:hidden;">Authorize and Load Events</button>
    <button id="revokeBtn" style="visibility:hidden;">Revoke Access</button>
    <div id="content"></div>

    <script>
        const YOUR_CLIENT_ID = "YOUR_CLIENT_ID";
        const YOUR_API_KEY = 'YOUR_API_KEY';
        const CALENDAR_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly';

        let tokenClient;
        let libsLoaded = 0;

        function gapiLoad() {
            gapi.load('client', initGapiClient);
        }

        async function initGapiClient() {
            try {
                await gapi.client.init({ apiKey: YOUR_API_KEY });
                await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
                console.log('GAPI client initialized.');
                checkAllLoaded();
            } catch (err) {
                handleError('GAPI initialization failed:', err);
            }
        }

        function gisLoad() {
            try {
                tokenClient = google.accounts.oauth2.initTokenClient({
                    client_id: YOUR_CLIENT_ID,
                    scope: CALENDAR_SCOPE,
                    callback: '', // Will be set dynamically
                    error_callback: handleGisError,
                });
                console.log('GIS TokenClient initialized.');
                checkAllLoaded();
            } catch (err) {
                handleError('GIS initialization failed:', err);
            }
        }

        function checkAllLoaded() {
            libsLoaded++;
            if (libsLoaded === 2) {
                document.getElementById('authorizeBtn').style.visibility = 'visible';
                document.getElementById('revokeBtn').style.visibility = 'visible';
                document.getElementById('authorizeBtn').onclick = makeApiCall;
                document.getElementById('revokeBtn').onclick = revokeAccess;
                console.log('Ready to authorize.');
            }
        }

        function handleGisError(err) {
            console.error('GIS Error:', err);
            let message = 'An error occurred during authorization.';
            if (err && err.type === 'popup_failed_to_open') {
                message = 'Failed to open popup. Please disable popup blockers.';
            } else if (err && err.type === 'popup_closed') {
                message = 'Authorization popup was closed.';
            }
            document.getElementById('content').textContent = message;
        }

        function handleError(message, error) {
            console.error(message, error);
            document.getElementById('content').textContent = `${message} ${error.message || JSON.stringify(error)}`;
        }

        async function makeApiCall() {
            document.getElementById('content').textContent = 'Processing...';
            try {
                let token = gapi.client.getToken();
                if (!token || !token.access_token) {
                    console.log('No token, fetching one...');
                    await getToken();
                }

                console.log('Calling Calendar API...');
                const response = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
                displayEvents(response.result);
            } catch (err) {
                console.error('API call failed:', err);
                const errorInfo = err.result && err.result.error;
                if (errorInfo && (errorInfo.code === 401 || (errorInfo.code === 403 && errorInfo.status === "PERMISSION_DENIED"))) {
                    console.log('Auth error on API call, refreshing token...');
                    try {
                        await getToken({ prompt: 'consent' }); // Force refresh
                        const retryResponse = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
                        displayEvents(retryResponse.result);
                    } catch (refreshErr) {
                        handleError('Failed to refresh token or retry API call:', refreshErr);
                    }
                } else {
                    handleError('Error loading events:', err.result ? err.result.error : err);
                }
            }
        }

        async function getToken(options = { prompt: '' }) {
            return new Promise((resolve, reject) => {
                if (!tokenClient) return reject(new Error("GIS TokenClient not initialized."));
                tokenClient.callback = (tokenResponse) => {
                    if (tokenResponse.error) {
                        reject(new Error(`Token Error: ${tokenResponse.error} - ${tokenResponse.error_description}`));
                    } else {
                        console.log('Token acquired.');
                        resolve(tokenResponse);
                    }
                };
                tokenClient.requestAccessToken(options);
            });
        }

        function displayEvents(result) {
            const events = result.items;
            if (events && events.length > 0) {
                let eventList = '<h3>Upcoming Events:</h3><ul>' + events.map(event =>
                    `<li>${event.summary} (${event.start.dateTime || event.start.date})</li>`
                ).join('') + '</ul>';
                document.getElementById('content').innerHTML = eventList;
            } else {
                document.getElementById('content').textContent = 'No upcoming events found.';
            }
        }

        function revokeAccess() {
            const token = gapi.client.getToken();
            if (token && token.access_token) {
                google.accounts.oauth2.revoke(token.access_token, () => {
                    console.log('Access revoked.');
                    document.getElementById('content').textContent = 'Access has been revoked.';
                    gapi.client.setToken(null);
                });
            } else {
                document.getElementById('content').textContent = 'No token to revoke.';
            }
        }
    </script>
</body>
</html>

GAPI-Callback

In diesem Beispiel wird gezeigt, wie Sie die Google Identity Services-Bibliothek mit dem Tokenmodell hinzufügen, das gapi.auth2-Modul entfernen und eine API mit der Google API-Clientbibliothek für JavaScript aufrufen.

Variablen werden verwendet, um die Ladereihenfolge von Bibliotheken zu erzwingen. GAPI-Aufrufe erfolgen über den Callback, nachdem ein gültiges Zugriffstoken zurückgegeben wurde.

Nutzer müssen die Schaltfläche „Kalender anzeigen“ drücken, wenn die Seite zum ersten Mal geladen wird, und noch einmal, wenn sie ihre Kalenderinformationen aktualisieren möchten.

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

Beispiele für den Autorisierungscode-Ablauf

Für das Pop-up-UX der Google Identity Service-Bibliothek kann entweder eine URL-Weiterleitung verwendet werden, um einen Autorisierungscode direkt an den Backend-Token-Endpunkt zurückzugeben, oder ein JavaScript-Callback-Handler, der im Browser des Nutzers ausgeführt wird und die Antwort an Ihre Plattform weiterleitet. In beiden Fällen schließt Ihre Backend-Plattform den OAuth 2.0-Ablauf ab, um ein gültiges Aktualisierungs- und Zugriffstoken zu erhalten.

Die alte Methode

Serverseitige Web-Apps

Google Log-in für serverseitige Apps, die auf einer Backend-Plattform ausgeführt werden und eine Weiterleitung zu Google zur Einholung der Nutzereinwilligung verwenden.

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

HTTP/REST mit Weiterleitung

OAuth 2.0 für Webserveranwendungen verwenden, um den Autorisierungscode vom Browser des Nutzers an Ihre Backend-Plattform zu senden. Die Nutzereinwilligung wird durch Weiterleitung des Nutzerbrowsers an Google eingeholt.

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

Jetzt

GIS-Pop-up-Benutzeroberfläche

In diesem Beispiel wird nur die Google Identity Services JavaScript-Bibliothek mit dem Autorisierungscode-Modell verwendet, um ein Pop-up-Dialogfeld für die Nutzereinwilligung und einen Callback-Handler zum Empfangen des Autorisierungscodes von Google zu erstellen. Es soll die Mindestanzahl der Schritte veranschaulichen, die zum Konfigurieren eines Clients, zum Einholen der Einwilligung und zum Senden eines Autorisierungscodes an Ihre Backend-Plattform erforderlich sind.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

GIS-Weiterleitung – UX

Das Autorisierungscode-Modell unterstützt die UX-Modi „Pop-up“ und „Weiterleitung“, um einen Autorisierungscode pro Nutzer an den von Ihrer Plattform gehosteten Endpunkt zu senden. Der UX-Modus für die Weiterleitung wird hier gezeigt:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

JavaScript-Bibliotheken

Google Identity Services ist eine einzelne JavaScript-Bibliothek, die für die Nutzerauthentifizierung und ‑autorisierung verwendet wird. Sie fasst Funktionen und Funktionalitäten aus verschiedenen Bibliotheken und Modulen zusammen und ersetzt sie:

Maßnahmen bei der Migration zu Identity Services:

Vorhandene JS-Bibliothek Neue JS-Bibliothek Hinweise
apis.google.com/js/api.js accounts.google.com/gsi/client Fügen Sie eine neue Bibliothek hinzu und folgen Sie dem impliziten Ablauf.
apis.google.com/js/client.js accounts.google.com/gsi/client Fügen Sie eine neue Bibliothek und den Autorisierungscode-Ablauf hinzu.

Kurzreferenz für Bibliotheken

Vergleich von Objekt und Methode zwischen der alten Google Sign-In JavaScript-Client-Bibliothek und der neuen Google Identity Services-Bibliothek sowie Hinweise mit zusätzlichen Informationen und Maßnahmen, die während der Migration zu ergreifen sind.

Alt Neu Hinweise
GoogleAuth -Objekt und zugehörige Methoden:
GoogleAuth.attachClickHandler() Entfernen
GoogleAuth.currentUser.get() Entfernen
GoogleAuth.currentUser.listen() Entfernen
GoogleAuth.disconnect() google.accounts.oauth2.revoke Ersetzen Sie das alte durch das neue. Der Widerruf kann auch über https://myaccount.google.com/permissions erfolgen.
GoogleAuth.grantOfflineAccess() Entfernen: Folgen Sie dem Autorisierungscode-Ablauf.
GoogleAuth.isSignedIn.get() Entfernen
GoogleAuth.isSignedIn.listen() Entfernen
GoogleAuth.signIn() Entfernen
GoogleAuth.signOut() Entfernen
GoogleAuth.then() Entfernen
GoogleUser -Objekt und zugehörige Methoden:
GoogleUser.disconnect() google.accounts.id.revoke Ersetzen Sie das alte durch das neue. Der Widerruf kann auch über https://myaccount.google.com/permissions erfolgen.
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() Alte durch neue ersetzen
GoogleUser.getBasicProfile() Entfernen. Verwenden Sie stattdessen ein ID-Token. Weitere Informationen finden Sie unter Von Google Log-in migrieren.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() Alte durch neue ersetzen
GoogleUser.getHostedDomain() Entfernen
GoogleUser.getId() Entfernen
GoogleUser.grantOfflineAccess() Entfernen: Folgen Sie dem Autorisierungscode-Ablauf.
GoogleUser.grant() Entfernen
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() Alte durch neue ersetzen
GoogleUser.isSignedIn() Entfernen
GoogleUser.reloadAuthResponse() requestAccessToken() Entfernen Sie den alten Aufruf und rufen Sie den neuen auf, um ein abgelaufenes oder widerrufenes Zugriffstoken zu ersetzen.
gapi.auth2 -Objekt und zugehörige Methoden:
gapi.auth2.AuthorizeConfig-Objekt TokenClientConfig oder CodeClientConfig Alte durch neue ersetzen
gapi.auth2.AuthorizeResponse-Objekt Entfernen
gapi.auth2.AuthResponse-Objekt Entfernen
gapi.auth2.authorize() requestCode() or requestAccessToken() Alte durch neue ersetzen
gapi.auth2.ClientConfig() TokenClientConfig oder CodeClientConfig Alte durch neue ersetzen
gapi.auth2.getAuthInstance() Entfernen
gapi.auth2.init() initTokenClient() or initCodeClient() Alte durch neue ersetzen
gapi.auth2.OfflineAccessOptions-Objekt Entfernen
gapi.auth2.SignInOptions-Objekt Entfernen
gapi.signin2 -Objekt und zugehörige Methoden:
gapi.signin2.render() Entfernen. Das Laden des HTML-DOM des Elements g_id_signin oder der JS-Aufruf von google.accounts.id.renderButton löst die Nutzeranmeldung in einem Google-Konto aus.

Beispielanmeldedaten

Vorhandene Anmeldedaten

Die Google Sign-In-Plattformbibliothek, die Google API Client Library for JavaScript oder direkte Aufrufe von Google OAuth 2.0-Endpunkten geben sowohl ein OAuth 2.0-Zugriffstoken als auch ein OpenID Connect-ID-Token in einer einzigen Antwort zurück.

Beispielantwort mit access_token und id_token:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

Anmeldedaten für Google Identity Services

Die Google Identity Services-Bibliothek gibt Folgendes zurück:

  • entweder ein Zugriffstoken, wenn es zur Autorisierung verwendet wird:

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • oder ein ID-Token, wenn es zur Authentifizierung verwendet wird:

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

Ungültige Tokenantwort

Beispielantwort von Google, wenn versucht wird, eine API-Anfrage mit einem abgelaufenen, widerrufenen oder ungültigen Zugriffstoken zu stellen:

HTTP-Antwortheader

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

Antworttext

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }