Migracja do Google Identity Services

Opis

Aby uzyskać dla każdego użytkownika token dostępu do wywoływania interfejsów API Google, Google udostępnia wiele bibliotek JavaScript:

Ten przewodnik zawiera instrukcje migracji z tych bibliotek do biblioteki usług tożsamości Google.

Postępując zgodnie z tym przewodnikiem:

  • Zastąp wycofywaną bibliotekę Platform biblioteką Identity Services,
  • Jeśli używasz biblioteki klienta API, usuń wycofany moduł gapi.auth2 oraz jego metody i obiekty, zastępując je odpowiednikami usług Identity Services.

Aby dowiedzieć się, co się zmieniło w bibliotece JavaScript usług tożsamości, przeczytaj omówienie oraz zapoznaj się z najważniejszymi terminami i koncepcjami dotyczącymi tego, jak działa autoryzacja użytkownika.

Jeśli interesuje Cię uwierzytelnianie podczas rejestracji i logowania użytkowników, przeczytaj artykuł Migracja z logowania przez Google.

Identyfikowanie przepływu autoryzacji

Istnieją 2 procesy autoryzacji użytkownika: kod niejawny i kod autoryzacji.

Sprawdź w aplikacji internetowej, jaki typ przepływu autoryzacji jest obecnie używany.

Wskazania aplikacji internetowej, która korzysta z przepływu niejawnego:

Wskazania aplikacji internetowej, która korzysta z przepływu kodu autoryzacji:

W niektórych przypadkach baza kodu może obsługiwać oba przepływy.

Wybierz proces autoryzacji

Przed rozpoczęciem migracji musisz określić, czy kontynuowanie obecnego procesu migracji jest możliwe, czy przyjęcie innego, najlepiej odpowiadającego Twoim potrzebom.

Zapoznaj się z artykułem o wybieraniu procesu autoryzacji, by zrozumieć najważniejsze różnice i wady między tymi dwoma przepływami.

W większości przypadków zalecany jest przepływ kodu autoryzacji, ponieważ zapewnia najwyższy poziom bezpieczeństwa użytkowników. Wdrożenie tego procesu ułatwia też dodawanie na platformie nowych funkcji offline, takich jak pobieranie aktualizacji w celu powiadamiania użytkowników o ważnych zmianach w ich kalendarzach, zdjęciach, subskrypcjach itd.

Wybierz proces autoryzacji, korzystając z selektorów poniżej.

Przepływ niejawny

Uzyskaj token dostępu do użytku w przeglądarce, gdy użytkownik jest obecny.

Przykłady przepływu niejawnego pokazują aplikacje internetowe przed migracją do usług tożsamości i po niej.

Przepływ kodu autoryzacji

Kod autoryzacji dla poszczególnych użytkowników wydany przez Google jest dostarczany na Twoją platformę backendu, gdzie jest wymieniany na token dostępu i token odświeżania.

Przykłady przepływu kodu autoryzacji pokazują aplikacje internetowe przed migracją do usług Identity Services i po niej.

W tym przewodniku postępuj zgodnie z pogrubionymi instrukcjami dodawania, usuwania, aktualizowania lub zastępowania istniejących funkcji.

Zmiany w Twojej aplikacji internetowej w przeglądarce

W tej sekcji znajdziesz informacje o zmianach, które wprowadzisz w aplikacji internetowej w przeglądarce podczas migracji do biblioteki JavaScript usług Google Identity Services.

Identyfikacja kodu, którego dotyczy problem, i testowanie

Plik cookie debugowania może pomóc w zlokalizowaniu kodu, którego dotyczy problem, i przetestowaniu, co się dzieje po wycofaniu.

W dużych lub złożonych aplikacjach znalezienie całego kodu, na który wpływa wycofanie modułu gapi.auth2, może być trudne. Aby rejestrować w konsoli bieżące użycie funkcji, które wkrótce zostaną wycofane, ustaw wartość pliku cookie G_AUTH2_MIGRATION na informational. Opcjonalnie dodaj dwukropek, a po nim parę klucz-wartość, aby zalogować się także w pamięci sesji. Po zalogowaniu się i otrzymaniu danych logowania przejrzyj zebrane logi lub wyślij zebrane logi do backendu w celu późniejszej analizy. Na przykład informational:showauth2use zapisuje źródło i adres URL w kluczu pamięci sesji o nazwie showauth2use.

Aby sprawdzić działanie aplikacji, gdy moduł gapi.auth2 nie jest już wczytywany, ustaw wartość pliku cookie G_AUTH2_MIGRATION na enforced. Umożliwi to testowanie działania działań po wycofaniu jeszcze przed datą wejścia w życie postanowień.

Możliwe wartości plików cookie G_AUTH2_MIGRATION:

  • enforced Nie wczytuj modułu gapi.auth2.
  • informational Rejestruj w konsoli JS użycie wycofanych funkcji. Loguj się też w pamięci sesji, gdy ustawiona jest opcjonalna nazwa klucza: informational:key-name.

Aby zminimalizować wpływ na użytkowników, zalecamy, aby najpierw ustawić ten plik cookie lokalnie na etapie programowania i testowania, a dopiero potem wykorzystać go w środowiskach produkcyjnych.

Biblioteki i moduły

Moduł gapi.auth2 zarządza uwierzytelnianiem użytkowników na potrzeby logowania i niejawnym przepływem autoryzacji. Zastępuje ten wycofany moduł oraz jego obiekty i metody biblioteką usług tożsamości Google.

Dodaj bibliotekę usług tożsamości do aplikacji internetowej, uwzględniając ją w dokumencie:

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

Usuń wszystkie wystąpienia wczytywania modułu auth2 za pomocą gapi.load('auth2', function).

Biblioteka Google Identity Services zastępuje moduł gapi.auth2. Możesz nadal bezpiecznie korzystać z modułu gapi.client z biblioteki klienta interfejsu API Google dla języka JavaScript oraz korzystać z automatycznego tworzenia wywoływanych metod JS z dokumentu wykrywania, grupowania wielu wywołań interfejsu API i funkcji zarządzania CORS.

Ciastka

Autoryzacja użytkownika nie wymaga używania plików cookie.

Więcej informacji o tym, jak uwierzytelnianie użytkowników korzysta z plików cookie, znajdziesz w artykule Migracja z logowania przez Google oraz Jak Google używa plików cookie w innych usługach Google.

Dane uwierzytelniające

Usługi tożsamości Google rozdzielają uwierzytelnianie i autoryzację użytkownika na 2 oddzielne operacje, a dane logowania użytkownika są oddzielne: token tożsamości używany do identyfikowania użytkownika jest zwracany niezależnie od tokena dostępu używanego do autoryzacji.

Aby wyświetlić te zmiany, zobacz przykładowe dane logowania.

Przepływ niejawny

Oddziel uwierzytelnianie i autoryzację użytkownika, usuwając obsługę profilu użytkownika z procesów autoryzacji.

Usuń te odwołania klienta JavaScriptu do logowania się przez Google:

Metody

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

Przepływ kodu autoryzacji

Identity Services rozdziela dane logowania w przeglądarce na token tożsamości i token dostępu. Nie dotyczy ona danych logowania uzyskanych przez bezpośrednie wywołania punktów końcowych Google OAuth 2.0 z Twojej platformy backendu lub z bibliotek działających na bezpiecznym serwerze w Twojej platformie, np. przez klienta Google API Node.js.

Stan sesji

Wcześniej Logowanie przez Google umożliwiało zarządzanie stanem zalogowania użytkownika za pomocą:

Odpowiadasz za zarządzanie stanem logowania i sesjami użytkowników w swojej aplikacji internetowej.

Usuń te odwołania klienta JavaScriptu do logowania się przez Google:

Obiekty:

  • gapi.auth2.SignInOptions

Metody:

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

Konfiguracja klienta

Zaktualizuj aplikację internetową, aby zainicjować klienta tokena na potrzeby przepływu kodu niejawnego lub autoryzacji.

Usuń te odwołania klienta JavaScriptu do logowania się przez Google:

Obiekty:

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

Metody:

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

Przepływ niejawny

Dodaj obiekt TokenClientConfig i wywołanie initTokenClient(), aby skonfigurować aplikację internetową zgodnie z przykładem podanym w artykule Inicjowanie klienta tokenów.

Zastąp odwołania klienta JavaScript logowania Google na Google Identity Services:

Obiekty:

  • gapi.auth2.AuthorizeConfigTokenClientConfig

Metody:

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

Parametry:

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

Przepływ kodu autoryzacji

Dodaj obiekt CodeClientConfig i wywołanie initCodeClient(), aby skonfigurować aplikację internetową zgodnie z przykładem podanym w artykule Inicjowanie klienta kodu.

Podczas przełączania z przepływu kodu niejawnego na przepływ kodu autoryzacji:

Usuń odwołania klienta JavaScript Log-In Google do logowania.

Obiekty:

  • gapi.auth2.AuthorizeConfig

Metody:

  • gapi.auth2.init()

Parametry:

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

Żądanie tokena

Gest użytkownika, na przykład kliknięcie przycisku, generuje żądanie, w wyniku którego token dostępu jest zwracany bezpośrednio do przeglądarki użytkownika za pomocą przepływu niejawnego lub do Twojej platformy backendu po wymianie kodu autoryzacji dla poszczególnych użytkowników na token dostępu i token odświeżania.

Przepływ niejawny

Tokeny dostępu można uzyskiwać i używać w przeglądarce, gdy użytkownik jest zalogowany i ma aktywną sesję z Google. W trybie niejawnym do żądania tokena dostępu wymagany jest gest użytkownika, nawet jeśli takie żądanie miało miejsce wcześniej.

Zastąp odwołania klienta JavaScript logowania Google na Google Identity Services:

Metody:

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

Dodaj link lub przycisk, aby wywołać requestAccessToken() w celu zainicjowania wyskakującego okienka UX, aby zażądać tokena dostępu lub uzyskać nowy token po wygaśnięciu istniejącego tokena.

Zaktualizuj bazę kodu do:

  • Wywołaj przepływ tokena OAuth 2.0 za pomocą requestAccessToken().
  • Obsługuj autoryzację przyrostową, używając requestAccessToken i OverridableTokenClientConfig, aby rozdzielać jedno żądanie dla wielu zakresów na kilka mniejszych żądań.
  • Poproś o nowy token, gdy istniejący token wygaśnie lub zostanie unieważniony.

Praca z wieloma zakresami może wymagać zmian strukturalnych w bazie kodu w celu żądania dostępu do zakresów tylko wtedy, gdy są potrzebne, a nie wszystkich naraz. Jest to tzw. autoryzacja przyrostowa. Każde żądanie powinno zawierać jak najmniejszą liczbę zakresów, a najlepiej jeden. Więcej informacji o aktualizowaniu aplikacji na potrzeby autoryzacji przyrostowej znajdziesz w artykule o obsłudze zgody użytkownika.

Po wygaśnięciu tokena dostępu moduł gapi.auth2 automatycznie otrzymuje nowy, prawidłowy token dostępu dla Twojej aplikacji internetowej. Aby zwiększyć bezpieczeństwo użytkowników, ten automatyczny proces odświeżania tokenów nie jest obsługiwany przez bibliotekę usług tożsamości Google. Musisz zaktualizować aplikację internetową, aby wykrywać wygasły token dostępu i prosić o nowy. Więcej informacji znajdziesz w sekcji Obsługa tokenów poniżej.

Przepływ kodu autoryzacji

Dodaj link lub przycisk, aby wywołać metodę requestCode() w celu zażądania od Google kodu autoryzacji. Przykład znajdziesz w artykule Aktywowanie przepływu kodu OAuth 2.0.

Więcej informacji o tym, jak zareagować na wygasły lub unieważniony token dostępu, znajdziesz poniżej w sekcji Obsługa tokenów.

Obsługa tokenów

Dodaj obsługę błędów, aby wykrywać nieudane wywołania interfejsu API Google w przypadku użycia wygasłego lub unieważnionego tokena dostępu i zażądać nowego, prawidłowego tokena dostępu.

W przypadku użycia wygasłego lub unieważnionego tokena dostępu przez interfejsy API Google zwracają kod stanu HTTP o błędzie 401 Unauthorized i invalid_token. Przykład znajdziesz w sekcji Nieprawidłowa odpowiedź tokena.

Wygasłe tokeny

Tokeny dostępu są ważne i często są ważne tylko przez kilka minut.

Unieważnienie tokena

W każdej chwili właściciel konta Google może cofnąć udzieloną wcześniej zgodę. Spowoduje to unieważnienie istniejących tokenów dostępu i tokenów odświeżania. Unieważnienie może być aktywowane z Twojej platformy za pomocą polecenia revoke() lub konta Google.

Zastąp odwołania klienta JavaScript logowania Google na Google Identity Services:

Metody:

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

Wywołaj metodę revoke, gdy użytkownik usunie swoje konto na Twojej platformie lub będzie chciał cofnąć zgodę na udostępnianie danych Twojej aplikacji.

Gdy Twoja aplikacja internetowa lub platforma backendu poprosi o token dostępu, Google wyświetla użytkownikowi okno z prośbą o zgodę na przetwarzanie danych osobowych. Zobacz przykładowe okna z prośbą o zgodę na wykorzystanie danych wyświetlane użytkownikom przez Google.

Przed wystawieniem tokena dostępu do aplikacji obowiązująca, aktywna sesja Google musi wyświetlić prośbę o zgodę użytkownika i zapisać wynik. Jeśli trwająca sesja nie została jeszcze rozpoczęta, użytkownik może być zmuszony do zalogowania się na konto Google.

Logowanie użytkownika

Użytkownicy mogą być zalogowani na konto Google na osobnej karcie przeglądarki albo bezpośrednio w przeglądarce lub systemie operacyjnym. Zalecamy dodanie do witryny funkcji Zaloguj się przez Google, aby nawiązać aktywną sesję między kontem Google a przeglądarką przy pierwszym uruchomieniu aplikacji przez użytkownika. Dzięki temu:

  • Zmniejsza liczbę razy, gdy użytkownik musi się zalogować. Żądanie tokena dostępu inicjuje proces logowania na konto Google, jeśli aktywna sesja jeszcze nie istnieje.
  • Użyj bezpośrednio pola danych logowania email tokena identyfikatora JWT jako wartości parametru login_hint w obiektach CodeClientConfig lub TokenClientConfig. Jest to szczególnie przydatne, jeśli na Twojej platformie nie ma systemu zarządzania kontami użytkowników.
  • Wyszukaj i powiąż konto Google z istniejącym lokalnym kontem użytkownika na swojej platformie, co pomaga zminimalizować liczbę zduplikowanych kont na Twojej platformie.
  • Po utworzeniu nowego konta lokalnego okno i proces rejestracji można wyraźnie oddzielić od okien i procesów uwierzytelniania użytkowników, co zmniejsza liczbę wymaganych kroków i poprawia współczynnik porzuceń.

Po zalogowaniu się, ale przed wystawieniem tokena dostępu użytkownicy muszą wyrazić zgodę na dostęp do aplikacji dla żądanych zakresów.

Po uzyskaniu zgody zwracany jest token dostępu wraz z listą zakresów zatwierdzonych lub odrzuconych przez użytkownika.

Szczegółowe uprawnienia pozwalają użytkownikom zatwierdzać i odrzucać poszczególne zakresy. Gdy poprosisz o dostęp do wielu zakresów, każdy z nich jest przyznawany lub odrzucany niezależnie od innych zakresów. Zależnie od wyboru użytkownika Twoja aplikacja wybiórczo włącza funkcje, które zależą od konkretnego zakresu.

Przepływ niejawny

Zastąp odwołania klienta JavaScript logowania Google na Google Identity Services:

Obiekty:

  • gapi.auth2.AuthorizeResponseTokenClient.TokenResponse
  • gapi.auth2.AuthResponseTokenClient.TokenResponse

Metody:

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

Usuń odwołania do klienta JavaScript logowania Google:

Metody:

  • GoogleUser.getAuthResponse()

Zaktualizuj aplikację internetową za pomocą zasad hasGrantedAllScopes() i hasGrantedAnyScope(), postępując zgodnie z tym przykładem szczegółowych uprawnień.

Przepływ kodu autoryzacji

Zaktualizuj lub dodaj punkt końcowy kodu autoryzacji do platformy backendu, wykonując instrukcje podane w sekcji Obsługa kodu autoryzacji.

Zaktualizuj platformę, wykonując czynności opisane w przewodniku Używanie modelu kodu w celu zweryfikowania żądania oraz uzyskania tokena dostępu i tokena odświeżania.

Zaktualizuj platformę, aby wybiórczo włączać lub wyłączać funkcje w zależności od poszczególnych zakresów zatwierdzonych przez użytkownika. Aby to zrobić, postępuj zgodnie z instrukcjami dodatkowej autoryzacji i sprawdź zakresy dostępu przyznane przez użytkownika.

Przykłady przepływu niejawnego

Stary sposób

Biblioteka klienta GAPI

Przykład biblioteki klienta interfejsu API Google dla języka JavaScript uruchomionej w przeglądarce z wyskakującym okienkiem z prośbą o zgodę na wykorzystanie danych użytkownika.

Moduł gapi.auth2 jest automatycznie ładowany i używany przez usługę gapi.client.init(), więc jest ukryty.

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

Biblioteka klienta JS

Protokół OAuth 2.0 dla aplikacji internetowych po stronie klienta działających w przeglądarce z wyskakującym okienkiem do wyrażenia zgody użytkownika.

Moduł gapi.auth2 jest wczytywany ręcznie.

<!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 API 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>

Punkty końcowe OAuth 2.0

Protokół OAuth 2.0 dla aplikacji internetowych po stronie klienta działających w przeglądarce przy użyciu przekierowań do Google w celu uzyskania zgody użytkownika.

Ten przykład przedstawia bezpośrednie wywołania Google punktów końcowych OAuth 2.0 z przeglądarki użytkownika i nie korzysta z modułu gapi.auth2 ani biblioteki JavaScript.

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

Nowy sposób

Tylko GIS

W tym przykładzie pokazujemy tylko bibliotekę JavaScript usługi Google Identity Service korzystającą z modelu tokena oraz wyskakujące okienko z prośbą o zgodę użytkownika. Przedstawiamy minimalną liczbę kroków wymaganych do skonfigurowania klienta, wysłania żądania i uzyskania tokena dostępu oraz wywołania interfejsu Google API.

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

Z tego przykładu dowiesz się, jak dodać bibliotekę Google Identity Service za pomocą modelu tokena, usunąć moduł gapi.auth2 i wywołać interfejs API za pomocą biblioteki klienta interfejsów API Google do obsługi JavaScriptu.

Obietnice, asynchroniczne i oczekiwania są używane do wymuszania kolejności wczytywania biblioteki oraz do wykrywania i ponawiania błędów autoryzacji. Wywołanie interfejsu API jest wykonywane dopiero wtedy, gdy dostępny jest prawidłowy token dostępu.

Użytkownicy powinni kliknąć przycisk „Pokaż kalendarz”, gdy brakuje tokena dostępu podczas pierwszego wczytywania strony lub później po jego wygaśnięciu.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

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

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await 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');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

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

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    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('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

Wywołanie zwrotne GAPI

Z tego przykładu dowiesz się, jak dodać bibliotekę Google Identity Service za pomocą modelu tokena, usunąć moduł gapi.auth2 i wywołać interfejs API za pomocą biblioteki klienta interfejsów API Google do obsługi JavaScriptu.

Zmienne służą do egzekwowania kolejności wczytywania biblioteki. Wywołania GAPI są wykonywane w obrębie wywołania zwrotnego po zwróceniu prawidłowego tokena dostępu.

Użytkownicy powinni nacisnąć przycisk Pokaż kalendarz przy pierwszym wczytaniu strony i ponownie, gdy będą chcieli odświeżyć informacje w Kalendarzu.

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

Przykłady przepływu kodu autoryzacji

Wyskakujące okienko biblioteki usług tożsamości Google może wykorzystywać przekierowanie adresu URL, aby zwrócić kod autoryzacji bezpośrednio do punktu końcowego tokena backendu, albo moduł obsługi wywołań zwrotnych JavaScript uruchamiany w przeglądarce użytkownika, który przekierowuje odpowiedź do platformy. W obu przypadkach platforma backendu ukończy proces OAuth 2.0, aby uzyskać prawidłowy token odświeżania i dostępu.

Stary sposób

Aplikacje internetowe po stronie serwera

Logowanie przez Google w aplikacjach po stronie serwera działających na platformie backendu z wykorzystaniem przekierowania do Google w celu uzyskania zgody użytkownika.

<!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 przy użyciu przekierowania

Korzystanie z protokołu OAuth 2.0 w aplikacjach serwerowych do wysyłania kodu autoryzacji z przeglądarki użytkownika na platformę backendu. Zgoda użytkownika jest obsługiwana przez przekierowanie jego przeglądarki do Google.

/\*
 \* 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();
}

Nowy sposób

Wyskakujące okienko GIS – UX

W tym przykładzie widać tylko bibliotekę JavaScript usługi Google Identity Service korzystającą z modelu kodu autoryzacji – wyskakujące okienko z prośbą o zgodę użytkownika i moduł obsługi wywołania zwrotnego do odbioru kodu autoryzacji od Google. Ilustracja pokazująca minimalną liczbę kroków wymaganych do skonfigurowania klienta, uzyskania zgody i wysłania kodu autoryzacji na platformę backendu.

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

Przekierowanie GIS do UX

Model kodu autoryzacji obsługuje tryby UX wyskakujących okienek i przekierowań, aby wysyłać kod autoryzacji poszczególnych użytkowników do punktu końcowego hostowanego przez Twoją platformę. Tryb UX przekierowania wygląda tak:

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

Biblioteki JavaScript

Google Identity Services to pojedyncza biblioteka JavaScript używana do uwierzytelniania i autoryzacji użytkowników, która konsoliduje i zastępuje funkcje dostępne w wielu różnych bibliotekach i modułach:

Czynności, które należy wykonać podczas migracji do Identity Services:

Istniejąca biblioteka JS Nowa biblioteka JS Uwagi
apis.google.com/js/api.js accounts.google.com/gsi/client Dodaj nową bibliotekę i postępuj zgodnie z instrukcjami.
apis.google.com/js/client.js accounts.google.com/gsi/client Dodaj nową bibliotekę i przepływ kodu autoryzacji.

Krótki przewodnik po bibliotece

Porównanie obiektów i metod starej biblioteki klienta JavaScript Google Sign-In JavaScript z biblioteką nowych Google Identity Services oraz Notatek z dodatkowymi informacjami i działaniami do wykonania podczas migracji.

Stara wersja Nowi Uwagi
Obiekt GoogleAuth i powiązane metody:
GoogleAuth.attachClickHandler() Usuń
GoogleAuth.currentUser.get() Usuń
GoogleAuth.currentUser.listen() Usuń
GoogleAuth.disconnect() google.accounts.oauth2.revoke Zastąp starą wersję nowym. Odwołanie może też nastąpić na stronie https://myaccount.google.com/permissions.
GoogleAuth.grantOfflineAccess() Usuń, postępuj zgodnie z instrukcjami dotyczącymi kodu autoryzacji.
GoogleAuth.isSignedIn.get() Usuń
GoogleAuth.isSignedIn.listen() Usuń
GoogleAuth.signIn() Usuń
GoogleAuth.signOut() Usuń
GoogleAuth.then() Usuń
Obiekt GoogleUser i powiązane metody:
GoogleUser.disconnect() google.accounts.id.revoke Zastąp starą wersję nowym. Odwołanie może też nastąpić na stronie https://myaccount.google.com/permissions.
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() Zamień stare na nowe
GoogleUser.getBasicProfile() Usuń. Zamiast tego użyj tokena identyfikatora, podanych w sekcji Migracja z usługi Google Sign-In (w języku angielskim).
GoogleUser.getGrantedScopes() hasGrantedAnyScope() Zamień stare na nowe
GoogleUser.getHostedDomain() Usuń
GoogleUser.getId() Usuń
GoogleUser.grantOfflineAccess() Usuń, postępuj zgodnie z instrukcjami dotyczącymi kodu autoryzacji.
GoogleUser.grant() Usuń
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() Zamień stare na nowe
GoogleUser.isSignedIn() Usuń
GoogleUser.reloadAuthResponse() requestAccessToken() Usuń stary, wywołaj nowy, aby zastąpić wygasły lub unieważniony token dostępu.
gapi.auth2 i powiązane metody:
Obiekt gapi.auth2.AuthorizeConfig TokenClientConfig lub CodeClientConfig Zamień stare na nowe
Obiekt gapi.auth2.AuthorizeResponse Usuń
Obiekt gapi.auth2.AuthResponse Usuń
gapi.auth2.authorize() requestCode() or requestAccessToken() Zamień stare na nowe
gapi.auth2.ClientConfig() TokenClientConfig lub CodeClientConfig Zamień stare na nowe
gapi.auth2.getAuthInstance() Usuń
gapi.auth2.init() initTokenClient() or initCodeClient() Zamień stare na nowe
Obiekt gapi.auth2.OfflineAccessOptions Usuń
Obiekt gapi.auth2.SignInOptions Usuń
gapi.signin2 i powiązane metody:
gapi.signin2.render() Usuń. Wczytanie HTML DOM elementu g_id_signin lub wywołanie JS google.accounts.id.renderButton powoduje zalogowanie użytkownika na konto Google.

Przykładowe dane logowania

Obecne dane logowania

Biblioteka platformy logowania Google, biblioteka klienta interfejsu API Google do języka JavaScript lub bezpośrednie wywołania Google Auth 2.0 w jednej odpowiedzi zwracają zarówno token dostępu OAuth 2.0, jak i token identyfikatora OpenID Connect.

Przykładowa odpowiedź zawierająca zarówno atrybuty access_token, jak i 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"
  }

Dane logowania do usług tożsamości Google

Biblioteka usług tożsamości Google zwraca:

  • token dostępu używany do autoryzacji:

    {
      "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"
    }
    
  • albo token tożsamości używany do uwierzytelniania:

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

Nieprawidłowa odpowiedź tokena

Przykładowa odpowiedź Google podczas próby wysłania żądania do interfejsu API przy użyciu wygasłego, unieważnionego lub nieprawidłowego tokena dostępu:

Nagłówki odpowiedzi HTTP

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

Treść odpowiedzi

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