Zu Google Identity Services migrieren

Übersicht

Google bietet mehrere JavaScript-Bibliotheken, mit denen Sie ein Zugriffstoken pro Nutzer abrufen können, um Google APIs aufzurufen:

In diesem Leitfaden finden Sie eine Anleitung zur Migration von diesen Bibliotheken zur Google Identity Services-Bibliothek.

In diesem Leitfaden erfahren Sie, wie Sie:

  • die veraltete Plattformbibliothek durch die Identity Services-Bibliothek ersetzen und
  • Wenn Sie die API-Clientbibliothek verwenden, entfernen Sie das verworfene gapi.auth2-Modul, seine Methoden und Objekte und ersetzen Sie sie durch die entsprechenden Identitätsdienst-Äquivalente.

Eine Beschreibung der Änderungen an der JavaScript-Bibliothek für Identitätsdienste finden Sie in der Übersicht und unter Funktionsweise der Nutzerautorisierung. Dort werden auch wichtige Begriffe und Konzepte erläutert.

Wenn Sie nach einer Authentifizierung für die Registrierung und Anmeldung von Nutzern suchen, lesen Sie stattdessen den Artikel Von Google Log-in migrieren.

Autorisierungsablauf ermitteln

Es gibt zwei mögliche Abläufe für die Nutzerautorisierung: implizit und Autorisierungscode.

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

Anzeichen dafür, dass Ihre Webanwendung den impliziten Ablauf verwendet:

  • Ihre Webanwendung ist rein browserbasiert 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 Webanwendung lädt apis.google.com/js/api.js.
  • Ihre Implementierung basiert auf OAuth 2.0 für clientseitige Webanwendungen.
  • Ihre App verwendet entweder das Modul gapi.client oder gapi.auth2 aus der Google API-Clientbibliothek für JavaScript.

Anzeichen dafür, 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 Endpunkt für den Autorisierungscode.

  • 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 den vorhandenen Ablauf beibehalten oder einen anderen Ablauf verwenden möchten, der Ihren Anforderungen besser entspricht.

Lesen Sie den Abschnitt Autorisierungsablauf auswählen, um die wichtigsten Unterschiede und Vor- und Nachteile der beiden Abläufe zu verstehen.

In den meisten Fällen wird der Autorisierungscode-Vorgang empfohlen, da er die höchste 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 Auswahl einen Autorisierungsablauf aus.

Impliziter Ablauf

Rufen Sie ein Zugriffstoken für die Verwendung im Browser ab, während der Nutzer anwesend ist.

Unter Beispiele für implizite Abläufe finden Sie Web-Apps vor und nach der Migration zu Identitätsdiensten.

Autorisierungscode-Vorgang

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

Unter Beispiele für den Autorisierungscode-Vorgang finden Sie Webanwendungen vor und nach der Migration zu Identitätsdiensten.

Folgen Sie in diesem Leitfaden den fett formatierten Anleitungen, um vorhandene Funktionen hinzuzufügen, zu entfernen, zu aktualisieren oder zu ersetzen.

Änderungen an Ihrer Web-App im Browser

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

Betroffenen Code identifizieren und testen

Mit einem Debug-Cookie können Sie den betroffenen Code finden und das Verhalten nach der Einstellung testen.

In 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 Console protokollieren möchten, setzen Sie den Wert des Cookies G_AUTH2_MIGRATION auf informational. Optional können Sie einen Doppelpunkt gefolgt von einem Schlüsselwert hinzufügen, um auch im Sitzungsspeicher zu protokollieren. Nach der Anmeldung und dem Erhalt der Anmeldedaten können Sie die erfassten Logs prüfen oder zur späteren Analyse an ein Backend senden. Beispiel: informational:showauth2use speichert Ursprung und URL in einem Sitzungsspeicherschlüssel mit dem Namen showauth2use.

Wenn Sie das Verhalten der Anwendung prüfen möchten, wenn das Modul gapi.auth2 nicht mehr geladen wird, setzen Sie den Wert des Cookies G_AUTH2_MIGRATION auf enforced. So kann das Verhalten nach der Einstellung vor dem Datum der Durchsetzung getestet werden.

Mögliche Werte für das G_AUTH2_MIGRATION-Cookie:

  • enforced Das Modul gapi.auth2 wird nicht geladen.
  • informational Protokolliert die Verwendung veralteter Funktionen in der JS-Konsole. Wenn ein optionaler Schlüsselname festgelegt ist, wird auch im Sitzungsspeicher protokolliert: 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 Modul gapi.auth2 verwaltet die Nutzerauthentifizierung für die Anmeldung und den impliziten Ablauf für die Autorisierung. Ersetzen Sie dieses veraltete Modul und seine Objekte und Methoden durch die Google Identity Services-Bibliothek.

Fügen Sie die Identitätsdienste-Bibliothek in Ihr Dokument ein, um sie Ihrer Webanwendung hinzuzufügen:

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

Entfernen Sie alle Instanzen, in denen das auth2-Modul mit gapi.load('auth2', function) geladen wird.

Die Google Identity Services-Bibliothek ersetzt die Verwendung des gapi.auth2-Moduls. Sie können das gapi.client-Modul aus der Google API-Clientbibliothek für JavaScript weiterhin verwenden und von der automatischen Erstellung aufrufbarer JS-Methoden aus einem Discovery-Dokument, der Batchverarbeitung mehrerer API-Aufrufe und der CORS-Verwaltungsfunktion profitieren.

Kekse

Für die Nutzerautorisierung sind keine Cookies erforderlich.

Weitere Informationen dazu, wie Cookies für die Nutzerauthentifizierung verwendet werden, finden Sie unter Von Google Log-in migrieren. Informationen zur Verwendung von Cookies durch andere Google-Produkte und ‑Dienste finden Sie unter So verwendet Google Cookies.

Anmeldedaten

Google Identity Services trennt die Nutzerauthentifizierung und -autorisierung in zwei unterschiedliche Vorgänge. Auch die Nutzeranmeldedaten sind getrennt: Das ID-Token zur Identifizierung eines Nutzers wird separat vom Zugriffstoken für die Autorisierung zurückgegeben.

Diese Änderungen finden Sie unter Beispielanmeldedaten.

Impliziter Ablauf

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

Entfernen Sie diese JavaScript-Clientreferenzen für Google Log-in:

Methoden

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

Autorisierungscode-Vorgang

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

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 in Ihrer Webanwendung verantwortlich.

Entfernen Sie diese JavaScript-Clientreferenzen für Google Log-in:

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 Webanwendung, um einen Token-Client für den impliziten oder Autorisierungscode-Vorgang zu initialisieren.

Entfernen Sie diese JavaScript-Clientreferenzen für Google Log-in:

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 Webanwendung zu konfigurieren. Folgen Sie dazu dem Beispiel unter Token-Client initialisieren.

Ersetzen Sie Referenzen auf den Google Log-in-JavaScript-Client 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-Vorgang

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

Beim Wechsel vom impliziten zum Autorisierungscode-Vorgang:

Entfernen Sie JavaScript-Clientreferenzen für Google Log-in.

Objekte:

  • gapi.auth2.AuthorizeConfig

Methoden:

  • gapi.auth2.init()

Parameter:

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

Tokenanfrage

Eine Nutzergeste, z. B. ein Klick auf eine Schaltfläche, generiert eine Anfrage, die dazu führt, dass ein Zugriffstoken direkt an den Browser des Nutzers zurückgegeben wird. Dies geschieht entweder über den impliziten Ablauf oder an Ihre Back-End-Plattform, nachdem ein nutzerspezifischer Autorisierungscode gegen ein Zugriffstoken und ein Aktualisierungstoken ausgetauscht wurde.

Impliziter Ablauf

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

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

Methoden:

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

Füge einen Link oder eine Schaltfläche hinzu, um requestAccessToken() aufzurufen und den Pop-up-UX-Ablauf zu starten, um ein Zugriffstoken anzufordern oder ein neues Token zu erhalten, wenn das vorhandene Token abläuft.

Aktualisieren Sie Ihre Codebasis auf:

  • OAuth 2.0-Token-Vorgang 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, müssen Sie möglicherweise strukturelle Änderungen an Ihrer Codebasis vornehmen, 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 enthalten, idealerweise nur einen einzigen. Weitere Informationen zum Aktualisieren Ihrer App für die inkrementelle Autorisierung finden Sie unter Nutzereinwilligung verwalten.

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

Autorisierungscode-Vorgang

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-Code-Flow auslösen.

Weitere Informationen zum Umgang mit abgelaufenen oder widerrufenen Zugriffstokens finden Sie im Abschnitt „Umgang mit Tokens“.

Token-Verarbeitung

Füge 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.

Wenn ein abgelaufenes oder widerrufenes Zugriffstoken verwendet wird, geben Google APIs den HTTP-Statuscode 401 Unauthorized und die Fehlermeldung invalid_token zurück. Ein Beispiel finden Sie unter Ungültige Tokenantwort.

Abgelaufene Tokens

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

Token-Widerruf

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

Ersetzen Sie JavaScript-Clientreferenzen für Google Log-in 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 zur Weitergabe von Daten an Ihre App widerrufen möchte.

Google zeigt dem Nutzer einen Dialog zur Einholung von Einwilligungen an, wenn entweder Ihre Web-App oder Ihre Backend-Plattform ein Zugriffstoken anfordert. Beispiele für Dialoge zur Einholung von Einwilligungen, die Google Nutzern anzeigt

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

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, Über 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:

  • Minimiert die Anzahl der Anmeldungen, die ein Nutzer vornehmen muss. Wenn ein Zugriffstoken angefordert wird, wird der Anmeldevorgang für das Google-Konto gestartet, sofern noch keine aktive Sitzung vorhanden ist.
  • Direkte Verwendung des Anmeldedatenfelds email des JWT-ID-Tokens als Wert des Parameters login_hint in CodeClientConfig- oder TokenClientConfig-Objekten. Das ist besonders hilfreich, wenn auf Ihrer Plattform kein System zur Verwaltung von Nutzerkonten vorhanden ist.
  • Google-Konto suchen und mit einem vorhandenen lokalen Nutzerkonto auf Ihrer Plattform verknüpfen, um doppelte Konten auf Ihrer Plattform zu minimieren.
  • Wenn ein neues, lokales Konto erstellt wird, können die Dialogfelder und Abläufe für die Registrierung klar von den Dialogfeldern und Abläufen für die Nutzerauthentifizierung getrennt werden. Dadurch wird die Anzahl der erforderlichen Schritte reduziert und die Abbruchrate verbessert.

Nach der Anmeldung und vor der Ausstellung eines Zugriffstokens 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 Bereiche 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. Je nach Nutzerauswahl werden in Ihrer App selektiv Funktionen aktiviert, die von einem einzelnen Bereich abhängen.

Impliziter Ablauf

Ersetzen Sie Referenzen auf den Google Log-in-JavaScript-Client 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 Sie die Referenzen auf den JavaScript-Client für Google Log-in:

Methoden:

  • GoogleUser.getAuthResponse()

Aktualisieren Sie Ihre Web-App mit hasGrantedAllScopes() und hasGrantedAnyScope(), indem Sie diesem Beispiel für differenzierte Berechtigungen folgen.

Autorisierungscode-Vorgang

Aktualisieren oder fügen Sie Ihrer Backend-Plattform einen Autorisierungscode-Endpunkt hinzu. Folgen Sie dazu der Anleitung unter Umgang mit Autorisierungscodes.

Aktualisieren Sie Ihre Plattform, um die im Leitfaden Codemodell verwenden beschriebenen Schritte auszuführen, um die Anfrage zu validieren und ein Zugriffs- und Aktualisierungstoken zu erhalten.

Aktualisiere deine Plattform, um Funktionen und Features selektiv zu aktivieren oder zu deaktivieren, je nachdem, welche Bereiche der Nutzer genehmigt hat. Folge dazu der Anleitung zur inkrementellen Autorisierung und prüfe die vom Nutzer gewährten Zugriffsbereiche.

Beispiele für implizite Abläufe

Früher

GAPI-Clientbibliothek

Beispiel für die Google API-Clientbibliothek für JavaScript, die im Browser ausgeführt wird und ein Pop-up-Dialogfeld für die Nutzereinwilligung verwendet.

Das Modul gapi.auth2 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 im Browser ausgeführt werden und ein Pop-up-Dialogfeld für die Nutzereinwilligung 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, wobei Weiterleitungen an den Google-Autorisierungsserver für die Nutzereinwilligung verwendet werden.

In diesem Beispiel werden direkte Aufrufe der OAuth 2.0-Endpunkte von Google über den Browser des Nutzers gezeigt. Das Modul gapi.auth2 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 the Google authorization 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 the Google authorization 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 von Google Identity Services mit dem Tokenmodell und dem Pop-up-Dialogfeld für die Nutzereinwilligung gezeigt. Es soll die minimale Anzahl von Schritten veranschaulichen, die erforderlich sind, um einen Client zu konfigurieren, ein Zugriffstoken anzufordern und zu erhalten und eine Google API aufzurufen.

<!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 Service-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 Ladereihenfolge der Bibliothek zu erzwingen und Autorisierungsfehler abzufangen und zu wiederholen. Ein API-Aufruf wird erst ausgeführt, 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 Service-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 der Bibliotheken zu erzwingen. GAPI-Aufrufe werden innerhalb des Callbacks ausgeführt, 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-Vorgang

Die Pop-up-UX der Google Identity Service-Bibliothek kann entweder eine URL-Weiterleitung verwenden, um einen Autorisierungscode direkt an den Token-Endpunkt Ihres Back-Ends zurückzugeben, oder einen 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-Vorgang ab, um ein gültiges Aktualisierungs- und Zugriffstoken zu erhalten.

Früher

Serverseitige Web-Apps

Google Log-in für serverseitige Apps, die auf einer Backend-Plattform ausgeführt werden, wobei eine Weiterleitung zu Google für die Nutzereinwilligung verwendet wird.

<!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 verarbeitet, indem der Browser des Nutzers an den Google-Autorisierungsserver weitergeleitet wird.

/*
 * Create form to request access token from the Google authorization 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-UX

In diesem Beispiel wird nur die JavaScript-Bibliothek von Google Identity Service gezeigt, die das Autorisierungscodemodell verwendet, ein Pop-up-Dialogfeld für die Nutzereinwilligung und einen Callback-Handler, um den Autorisierungscode von Google zu erhalten. Sie soll die Mindestanzahl von Schritten veranschaulichen, die erforderlich sind, um einen Client zu konfigurieren, die Einwilligung einzuholen und einen Autorisierungscode an Ihre Backend-Plattform zu senden.

<!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-Weiterleitungs-UX

Das Autorisierungscodemodell 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 konsolidiert und ersetzt Features und Funktionen, die in mehreren verschiedenen Bibliotheken und Modulen zu finden sind:

Maßnahmen bei der Migration zu Identitätsdiensten:

Vorhandene JS-Bibliothek Neue JS-Bibliothek Hinweise
apis.google.com/js/api.js accounts.google.com/gsi/client Fügen Sie die 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 hinzu und folgen Sie dem Autorisierungscode-Vorgang.

Kurzübersicht zur Bibliothek

Vergleich der Objekte und Methoden der alten Google Log-in JavaScript-Clientbibliothek 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 Sie den Autorisierungscode-Vorgang.
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() oder requestAccessToken() Alt durch neu ersetzen
GoogleUser.getBasicProfile() Entfernen. Verwende stattdessen das ID-Token. Weitere Informationen findest du unter Von Google Log-in migrieren.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() Altes durch Neues ersetzen
GoogleUser.getHostedDomain() Entfernen
GoogleUser.getId() Entfernen
GoogleUser.grantOfflineAccess() Entfernen Sie den Autorisierungscode-Vorgang.
GoogleUser.grant() Entfernen
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() Alt durch neu ersetzen
GoogleUser.isSignedIn() Entfernen
GoogleUser.reloadAuthResponse() requestAccessToken() Entfernen Sie das alte Token und rufen Sie das neue auf, um ein abgelaufenes oder widerrufenes Zugriffstoken zu ersetzen.
gapi.auth2-Objekt und zugehörige Methoden:
gapi.auth2.AuthorizeConfig Objekt TokenClientConfig oder CodeClientConfig Altes durch Neues ersetzen
gapi.auth2.AuthorizeResponse Objekt Entfernen
gapi.auth2.AuthResponse Objekt Entfernen
gapi.auth2.authorize() requestCode() oder requestAccessToken() Altes durch Neues ersetzen
gapi.auth2.ClientConfig() TokenClientConfig oder CodeClientConfig Alt durch neu ersetzen
gapi.auth2.getAuthInstance() Entfernen
gapi.auth2.init() initTokenClient() oder initCodeClient() Alt durch neu 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-Elements g_id_signin oder der JS-Aufruf von google.accounts.id.renderButton löst die Anmeldung des Nutzers bei einem Google-Konto aus.

Beispielanmeldedaten

Vorhandene Anmeldedaten

Die Google Log-in-Plattform-Bibliothek, die Google API-Clientbibliothek für 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"
  }

Google Identity Services-Anmeldedaten

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

  • entweder ein Zugriffstoken, wenn es für die 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 für die 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 senden:

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"
    }
  }