Przegląd
Aby uzyskać token dostępu dla użytkownika i wywołać interfejsy API Google, Google oferuje kilka bibliotek JavaScript:
- Biblioteka platformy logowania przez Google
- Biblioteka klienta interfejsów API Google do języka JavaScript
Z tego przewodnika dowiesz się, jak przejść z tych bibliotek na bibliotekę Google Identity Services.
Dzięki temu przewodnikowi:
- zastąp wycofaną bibliotekę Platform Library biblioteką usług tożsamości,
- Jeśli używasz biblioteki klienta interfejsu API, usuń wycofany moduł
gapi.auth2, jego metody i obiekty, zastępując je odpowiednikami z usług tożsamości.
Opis zmian w bibliotece JavaScriptu usług tożsamości znajdziesz w omówieniu i opisie działania autoryzacji użytkownika. Znajdziesz tam też najważniejsze terminy i pojęcia.
Jeśli szukasz uwierzytelniania na potrzeby rejestracji i logowania użytkowników, zapoznaj się z artykułem Migracja z Logowania przez Google.
Określanie procesu autoryzacji
Dostępne są 2 przepływy autoryzacji użytkownika: niejawny i kod autoryzacji.
Sprawdź aplikację internetową, aby określić typ używanego procesu autoryzacji.
Oznaki, że aplikacja internetowa używa przepływu niejawnego:
- Twoja aplikacja internetowa działa wyłącznie w przeglądarce i nie ma platformy backendowej.
- Użytkownik musi być obecny, aby wywoływać interfejsy API Google, aplikacja używa tylko tokenów dostępu i nie wymaga tokenów odświeżania.
- Aplikacja internetowa wczytuje
apis.google.com/js/api.js. - Twoja implementacja jest oparta na protokole OAuth 2.0 w aplikacjach internetowych po stronie klienta.
- Twoja aplikacja używa modułów
gapi.clientlubgapi.auth2, które znajdują się w bibliotece klienta interfejsu API Google dla języka JavaScript.
Oznaki, że aplikacja internetowa używa przepływu kodu autoryzacji:
Implementacja opiera się na:
Aplikacja działa zarówno w przeglądarce użytkownika, jak i na platformie backendu.
Twoja platforma backendowa hostuje punkt końcowy kodu autoryzacji.
Twoja platforma backendowa wywołuje interfejsy API Google w imieniu użytkowników bez konieczności ich obecności, co jest również znane jako tryb offline.
Tokeny odświeżania są zarządzane i przechowywane przez platformę backendu.
W niektórych przypadkach baza kodu może obsługiwać oba przepływy.
Wybieranie procesu autoryzacji
Przed rozpoczęciem migracji musisz określić, czy kontynuowanie dotychczasowego procesu, czy też przyjęcie innego, najlepiej odpowiada Twoim potrzebom.
Zapoznaj się z sekcją Wybieranie procesu autoryzacji, aby poznać najważniejsze różnice i kompromisy między tymi 2 procesami.
W większości przypadków zalecany jest przepływ kodu autoryzacji, ponieważ zapewnia on najwyższy poziom bezpieczeństwa użytkownika. Wdrożenie tego procesu umożliwia też platformie dodawanie nowych funkcji offline, takich jak pobieranie aktualizacji w celu powiadamiania użytkowników o istotnych zmianach w ich kalendarzu, zdjęciach i subskrypcjach.
Wybierz proces autoryzacji za pomocą selektorów.
Przepływ niejawny
uzyskiwanie tokena 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 użytkownika wydany przez Google jest dostarczany do Twojej platformy backendowej, gdzie jest następnie wymieniany na token dostępu i token odświeżania.
Przykłady przepływu kodu autoryzacji pokazują aplikacje internetowe przed migracją do usług tożsamości i po niej.
W tym przewodniku postępuj zgodnie z instrukcjami podanymi pogrubioną czcionką, aby dodać, usunąć, zaktualizować lub zastąpić dotychczasowe funkcje.
Zmiany w aplikacji internetowej w przeglądarce
W tej sekcji opisujemy zmiany, które wprowadzisz w aplikacji internetowej w przeglądarce podczas migracji do biblioteki JavaScriptu Google Identity Services.
Identyfikowanie kodu, którego dotyczy problem, i testowanie
Plik cookie debugowania może pomóc w zlokalizowaniu kodu, którego dotyczy problem, i przetestowaniu działania po wycofaniu.
W dużych lub złożonych aplikacjach znalezienie całego kodu, którego dotyczy wycofanie modułu gapi.auth2, może być trudne. Aby rejestrować w konsoli dotychczasowe użycie funkcji, która wkrótce zostanie wycofana, ustaw wartość pliku cookie G_AUTH2_MIGRATION na informational. Opcjonalnie możesz dodać dwukropek, a po nim wartość klucza, aby rejestrować dane również w pamięci sesji. Po zalogowaniu się i otrzymaniu danych logowania sprawdź lub wyślij zebrane dzienniki 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ć zachowanie aplikacji, gdy moduł gapi.auth2 nie jest już wczytywany, ustaw wartość pliku cookie G_AUTH2_MIGRATION na enforced. Umożliwi to przetestowanie działania po wycofaniu przed datą egzekwowania.
Możliwe wartości pliku cookie G_AUTH2_MIGRATION:
enforcedNie wczytuj moduługapi.auth2.informationalRejestruj użycie wycofanych funkcji w konsoli JS. Jeśli ustawiona jest opcjonalna nazwa klucza, zapisuj też w pamięci sesji:informational:key-name.
Aby zminimalizować wpływ na użytkowników, zalecamy najpierw ustawić ten plik cookie lokalnie podczas programowania i testowania, zanim zostanie użyty w środowiskach produkcyjnych.
Biblioteki i moduły
Moduł gapi.auth2 zarządza uwierzytelnianiem użytkowników na potrzeby logowania i przepływem niejawnym na potrzeby autoryzacji. Zastąp ten wycofany moduł oraz jego obiekty i metody biblioteką Google Identity Services.
Dodaj bibliotekę usług tożsamości do aplikacji internetowej, umieszczają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 bezpiecznie nadal używać modułu gapi.client z biblioteki klienta interfejsu API Google dla JavaScriptu i korzystać z automatycznego tworzenia wywoływalnych metod JS z dokumentu opisującego, grupowania wielu wywołań interfejsu API i funkcji zarządzania CORS.
Pliki cookie
Autoryzacja użytkownika nie wymaga użycia 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. Informacje o tym, jak inne usługi Google korzystają z plików cookie, znajdziesz w artykule Jak Google używa plików cookie.
Dane logowania
Usługi tożsamości Google rozdzielają uwierzytelnianie i autoryzację użytkowników na 2 odrębne operacje, a dane logowania użytkownika są oddzielne: token identyfikacji używany do identyfikacji użytkownika jest zwracany oddzielnie od tokena dostępu używanego do autoryzacji.
Aby zobaczyć te zmiany, zapoznaj się z przykładowymi danymi logowania.
Przepływ niejawny
Oddziel uwierzytelnianie użytkownika od autoryzacji, usuwając obsługę profilu użytkownika z procesów autoryzacji.
Usuń te odwołania do klienta JavaScriptu Logowania przez Google:
Metody
GoogleUser.getBasicProfile()GoogleUser.getId()
Przepływ kodu autoryzacji
Usługi tożsamości dzielą dane logowania w przeglądarce na token identyfikacji i token dostępu. Ta zmiana nie dotyczy danych logowania uzyskanych przez bezpośrednie wywołania punktów końcowych Google OAuth 2.0 z platformy backendu ani przez biblioteki działające na bezpiecznym serwerze na Twojej platformie, takie jak klient interfejsów API Google w Node.js.
Stan sesji
Wcześniej funkcja Logowanie przez Google pomagała zarządzać stanem zalogowania użytkownika za pomocą:
- Moduły obsługi wywołania zwrotnego do monitorowania stanu sesji użytkownika.
- Detektory zdarzeń i zmian stanu zalogowania na konto Google użytkownika.
Odpowiadasz za zarządzanie stanem logowania i sesjami użytkowników w aplikacji internetowej.
Usuń te odwołania do klienta JavaScriptu Logowania 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 niejawnego lub przepływu kodu autoryzacji.
Usuń te odwołania do klienta JavaScriptu Logowania przez Google:
Obiekty:
gapi.auth2.ClientConfiggapi.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 w sekcji Inicjowanie klienta tokena.
Zastąp odwołania do klienta JavaScript logowania przez Google odwołaniami do Google Identity Services:
Obiekty:
gapi.auth2.AuthorizeConfigiTokenClientConfig
Metody:
gapi.auth2.init()igoogle.accounts.oauth2.initTokenClient()
Parametry:
gapi.auth2.AuthorizeConfig.login_hintz:TokenClientConfig.login_hint.gapi.auth2.GoogleUser.getHostedDomain()przy użyciu stronyTokenClientConfig.hd.
Przepływ kodu autoryzacji
Dodaj obiekt CodeClientConfig i wywołanie initCodeClient(), aby skonfigurować aplikację internetową, zgodnie z przykładem w sekcji Inicjowanie klienta kodu.
Podczas przechodzenia z przepływu niejawnego na przepływ kodu autoryzacji:
Usuń odwołania do klienta JavaScript logowania przez Google.
Obiekty:
gapi.auth2.AuthorizeConfig
Metody:
gapi.auth2.init()
Parametry:
gapi.auth2.AuthorizeConfig.login_hintgapi.auth2.GoogleUser.getHostedDomain()
Żądanie tokena
Gest użytkownika, taki jak kliknięcie przycisku, generuje żądanie, które powoduje zwrócenie tokena dostępu bezpośrednio do przeglądarki użytkownika w ramach przepływu niejawnego lub do platformy backendu po wymianie kodu autoryzacji użytkownika na token dostępu i token odświeżania.
Przepływ niejawny
Tokeny dostępu można uzyskać i używać ich w przeglądarce, gdy użytkownik jest zalogowany i ma aktywną sesję w Google. W trybie niejawnym do żądania tokena dostępu wymagany jest gest użytkownika, nawet jeśli wcześniej wysłano żądanie.
Zastąp odwołania do klienta JavaScript logowania przez Google odwołaniami do Google Identity Services:
Metody:
gapi.auth2.authorize()iTokenClient.requestAccessToken()GoogleUser.reloadAuthResponse()z:TokenClient.requestAccessToken()
Dodaj link lub przycisk, który wywołuje funkcję requestAccessToken(), aby zainicjować proces UX wyskakującego okienka i poprosić o token dostępu lub uzyskać nowy token, gdy wygaśnie dotychczasowy.
Zaktualizuj bazę kodu, aby:
- Uruchom przepływ tokena OAuth 2.0 za pomocą
requestAccessToken(). - Obsługuj autoryzację przyrostową, używając
requestAccessTokeniOverridableTokenClientConfig, aby podzielić jedno żądanie dotyczące wielu zakresów na kilka mniejszych żądań. - Poproś o nowy token, gdy dotychczasowy wygaśnie lub zostanie unieważniony.
Praca z wieloma zakresami może wymagać zmian strukturalnych w bazie kodu, aby żądać dostępu do zakresów tylko wtedy, gdy są potrzebne, a nie wszystkich naraz. Jest to tzw. autoryzacja przyrostowa. Każda prośba powinna zawierać jak najmniej zakresów, najlepiej tylko jeden. Więcej informacji o aktualizowaniu aplikacji pod kątem autoryzacji przyrostowej znajdziesz w artykule o obsłudze zgody użytkownika.
Gdy token dostępu wygaśnie, moduł gapi.auth2 automatycznie uzyska nowy, ważny token dostępu dla Twojej aplikacji internetowej. Aby zwiększyć bezpieczeństwo użytkowników, biblioteka usług tożsamości Google nie obsługuje tego procesu automatycznego odświeżania tokena. Aplikacja internetowa musi zostać zaktualizowana, aby wykrywać wygasły token dostępu i prosić o nowy. Więcej informacji znajdziesz w sekcji Obsługa tokenów.
Przepływ kodu autoryzacji
Dodaj link lub przycisk, który wywołuje requestCode(), aby poprosić Google o kod autoryzacji. Przykład znajdziesz w sekcji Uruchamianie przepływu kodu OAuth 2.0.
Więcej informacji o tym, jak reagować na wygaśnięcie lub unieważnienie tokena dostępu, znajdziesz w sekcji Obsługa tokenów.
Obsługa tokenów
Dodaj obsługę błędów, aby wykrywać nieudane wywołania interfejsu API Google, gdy używany jest wygasły lub unieważniony token dostępu, i prosić o nowy, prawidłowy token dostępu.
Gdy używany jest wygasły lub unieważniony token dostępu, interfejsy API Google zwracają kod stanu HTTP 401 Unauthorized i komunikat o błędzie invalid_token. Przykład znajdziesz w sekcji Odpowiedź o nieprawidłowym tokenie.
Wygasłe tokeny
Tokeny dostępu mają krótki okres ważności, często tylko kilka minut.
Unieważnienie tokena
Właściciel konta Google może w każdej chwili wycofać wcześniej udzieloną zgodę. Spowoduje to unieważnienie istniejących tokenów dostępu i tokenów odświeżania. Unieważnienie można wywołać na platformie za pomocą revoke() lub na koncie Google.
Zastąp odwołania do klienta JavaScript logowania przez Google odwołaniami do Google Identity Services:
Metody:
getAuthInstance().disconnect()igoogle.accounts.oauth2.revoke()GoogleUser.disconnect()igoogle.accounts.oauth2.revoke()
Wywołaj revoke, gdy użytkownik usunie swoje konto na Twojej platformie lub zechce wycofać zgodę na udostępnianie danych Twojej aplikacji.
Prośba o zgodę użytkownika
Google wyświetla użytkownikowi okno z prośbą o zgodę na przetwarzanie danych osobowych, gdy aplikacja internetowa lub platforma backendu prosi o token dostępu. Zobacz przykładowe okna z prośbą o zgodę na przetwarzanie danych osobowych wyświetlane użytkownikom przez Google.
Przed wydaniem tokena dostępu aplikacji wymagana jest istniejąca i aktywna sesja Google, aby poprosić o zgodę użytkownika i zarejestrować wynik. Jeśli nie ma jeszcze aktywnej sesji, użytkownik może zostać poproszony o zalogowanie się na konto Google.
Logowanie użytkownika
Użytkownicy mogą być zalogowani na konto Google na osobnej karcie przeglądarki lub natywnie w przeglądarce lub systemie operacyjnym. Zalecamy dodanie do witryny funkcji Zaloguj się przez Google, aby ustanowić aktywną sesję między kontem Google a przeglądarką, gdy użytkownik po raz pierwszy otworzy aplikację. Zapewnia to te korzyści:
- Minimalizuje liczbę logowań użytkownika. Żądanie tokena dostępu inicjuje proces logowania na konto Google, jeśli nie ma jeszcze aktywnej sesji.
- Bezpośrednie użycie pola credential
emailtokena identyfikacji JWT jako wartości parametrulogin_hintw obiektachCodeClientConfiglubTokenClientConfig. Jest to szczególnie przydatne, jeśli Twoja platforma nie ma systemu zarządzania kontami użytkowników. - wyszukiwanie konta Google i powiązanie go z istniejącym lokalnym kontem użytkownika na Twojej platformie, co pomaga zminimalizować liczbę zduplikowanych kont na platformie;
- Podczas tworzenia nowego konta lokalnego okna i proces rejestracji mogą być wyraźnie oddzielone od okien i procesów uwierzytelniania użytkownika, co zmniejsza liczbę wymaganych kroków i poprawia współczynnik porzuceń.
Po zalogowaniu się, a przed wydaniem tokena dostępu, użytkownicy muszą wyrazić zgodę na dostęp aplikacji do żądanych zakresów.
Odpowiedź dotycząca tokena i zgody
Po wyrażeniu zgody zwracany jest token dostępu wraz z listą zakresów zatwierdzonych lub odrzuconych przez użytkownika.
Szczegółowe uprawnienia umożliwiają użytkownikom zatwierdzanie lub odrzucanie poszczególnych zakresów. W przypadku prośby o dostęp do wielu zakresów każdy z nich jest przyznawany lub odrzucany niezależnie od pozostałych. W zależności od wyboru użytkownika aplikacja selektywnie włącza funkcje, które zależą od poszczególnych zakresów.
Przepływ niejawny
Zastąp odwołania do klienta JavaScript logowania przez Google odwołaniami do Google Identity Services:
Obiekty:
gapi.auth2.AuthorizeResponseiTokenClient.TokenResponsegapi.auth2.AuthResponseiTokenClient.TokenResponse
Metody:
GoogleUser.hasGrantedScopes()z:google.accounts.oauth2.hasGrantedAllScopes()GoogleUser.getGrantedScopes()z:google.accounts.oauth2.hasGrantedAllScopes()
Usuń odwołania do klienta JavaScript logowania przez Google:
Metody:
GoogleUser.getAuthResponse()
Zaktualizuj aplikację internetową, dodając hasGrantedAllScopes() i hasGrantedAnyScope() zgodnie z tym przykładem uprawnień szczegółowych.
Przepływ kodu autoryzacji
Zaktualizuj lub dodaj punkt końcowy kodu autoryzacji na platformie backendu, postępując zgodnie z instrukcjami podanymi w sekcji Obsługa kodu autoryzacji.
Zaktualizuj platformę, aby postępować zgodnie z instrukcjami opisanymi w przewodniku Korzystanie z modelu kodu, aby zweryfikować żądanie i uzyskać token dostępu oraz token odświeżania.
Zaktualizuj swoją platformę, aby selektywnie włączać lub wyłączać funkcje na podstawie poszczególnych zakresów zatwierdzonych przez użytkownika. Aby to zrobić, postępuj zgodnie z instrukcjami dotyczącymi autoryzacji przyrostowej i sprawdzania zakresów dostępu przyznanych przez użytkownika.
Przykłady przepływu niejawnego
Stara metoda
Biblioteka klienta GAPI
Przykład biblioteki klienta interfejsu API Google dla języka JavaScript działającej w przeglądarce i wyświetlającej wyskakujące okienko z prośbą o zgodę użytkownika.
Moduł gapi.auth2 jest automatycznie wczytywany i używany przez gapi.client.init(), dlatego 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
OAuth 2.0 dla aplikacji internetowych po stronie klienta działających w przeglądarce, które używają wyskakującego okna do uzyskiwania 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 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>
Punkty końcowe OAuth 2.0
OAuth 2.0 w aplikacjach internetowych po stronie klienta działających w przeglądarce, które przekierowują do serwera autoryzacji Google w celu uzyskania zgody użytkownika.
Ten przykład pokazuje bezpośrednie wywołania punktów końcowych OAuth 2.0 Google z przeglądarki użytkownika i nie używa 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 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>
Nowy sposób
Tylko GIS
W tym przykładzie pokazujemy tylko bibliotekę JavaScript Google Identity Service korzystającą z modelu tokena i wyskakujące okno z prośbą o zgodę użytkownika. Ilustruje on minimalną liczbę kroków wymaganych do skonfigurowania klienta, wysłania żądania i uzyskania tokena dostępu oraz wywołania interfejsu API Google.
<!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
Ten przykład pokazuje, jak dodać bibliotekę Google Identity Service za pomocą modelu tokena, usunąć moduł gapi.auth2 i wywołać interfejs API za pomocą biblioteki klienta interfejsu API Google dla języka JavaScript.
Obiekty Promise, async i await są używane do wymuszania kolejności wczytywania bibliotek oraz do wychwytywania błędów autoryzacji i ponawiania prób. Wywołanie interfejsu API jest wykonywane tylko wtedy, gdy dostępny jest prawidłowy token dostępu.
Użytkownicy powinni nacisnąć przycisk „Pokaż kalendarz”, gdy brakuje tokena dostępu przy pierwszym wczytaniu strony lub później, gdy token dostępu wygaśnie.
<!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>
Wywołanie zwrotne GAPI
Ten przykład pokazuje, jak dodać bibliotekę Google Identity Service za pomocą modelu tokena, usunąć moduł gapi.auth2 i wywołać interfejs API za pomocą biblioteki klienta interfejsu API Google dla JavaScriptu.
Zmienne służą do wymuszania kolejności wczytywania bibliotek. Wywołania GAPI są wykonywane z 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 chcą odświeżyć informacje z kalendarza.
<!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 UX biblioteki Google Identity Service może używać przekierowania adresu URL, aby zwrócić kod autoryzacji bezpośrednio do punktu końcowego tokena backendu, lub modułu obsługi wywołania zwrotnego JavaScript działającego w przeglądarce użytkownika, który przekazuje odpowiedź do Twojej platformy. W obu przypadkach platforma backendu zakończy przepływ OAuth 2.0, aby uzyskać prawidłowy token odświeżania i token dostępu.
Stara metoda
Aplikacje internetowe po stronie serwera
Logowanie przez Google w aplikacjach po stronie serwera działających na platformie backendu, które przekierowują użytkownika do Google w celu uzyskania jego 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 z przekierowaniem,
Używanie OAuth 2.0 w internetowych aplikacjach serwerowych do wysyłania kodu autoryzacji z przeglądarki użytkownika do platformy backendowej. Zgoda użytkownika jest obsługiwana przez przekierowanie przeglądarki użytkownika na serwer autoryzacji Google.
/*
* 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 <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 UX GIS
Ten przykład pokazuje tylko bibliotekę JavaScript Google Identity Service korzystającą z modelu kodu autoryzacji, wyskakujące okno dialogowe zgody użytkownika i moduł obsługi wywołania zwrotnego do odbierania kodu autoryzacji od Google. Ilustruje on minimalną liczbę kroków wymaganych do skonfigurowania klienta, uzyskania zgody i wysłania kodu autoryzacji do platformy backendowej.
<!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 Redirect UX
Model kodu autoryzacji obsługuje tryby UX wyskakującego okienka i przekierowania, aby wysłać kod autoryzacji dla użytkownika do punktu końcowego hostowanego przez Twoją platformę. Tryb UX przekierowania jest pokazany tutaj:
<!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 JavaScriptu używana do uwierzytelniania i autoryzacji użytkowników, która konsoliduje i zastępuje funkcje i możliwości dostępne w wielu różnych bibliotekach i modułach:
- Klient JavaScriptu do logowania przez Google i
- Biblioteka klienta interfejsów API Google do języka JavaScript.
Działania, które należy wykonać podczas migracji do usług tożsamości:
| 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 przepływem niejawnym. |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
Dodaj nową bibliotekę i postępuj zgodnie z przepływem kodu autoryzacji. |
Krótkie omówienie biblioteki
Porównanie obiektów i metod między starszą biblioteką klienta JavaScript Logowania przez Google a nową biblioteką Google Identity Services oraz uwagi z dodatkowymi informacjami i działaniami, które należy wykonać podczas migracji.
| Stary | Nowy | 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 stare nowym. Uprawnienia można też cofnąć na stronie https://myaccount.google.com/permissions. |
GoogleAuth.grantOfflineAccess() |
Usuń, postępuj zgodnie z przepływem 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 stare nowym. Uprawnienia można też cofnąć na stronie https://myaccount.google.com/permissions. |
GoogleUser.getAuthResponse() |
requestCode() lub requestAccessToken() |
Zastąp stare nowymi |
GoogleUser.getBasicProfile() |
Usuń. Zamiast tego użyj tokena identyfikacji. Więcej informacji znajdziesz w artykule o migracji z funkcji Logowanie przez Google. | |
GoogleUser.getGrantedScopes() |
hasGrantedAnyScope() |
Zastąp stare nowymi |
GoogleUser.getHostedDomain() |
Usuń | |
GoogleUser.getId() |
Usuń | |
GoogleUser.grantOfflineAccess() |
Usuń, postępuj zgodnie z przepływem kodu autoryzacji. | |
GoogleUser.grant() |
Usuń | |
GoogleUser.hasGrantedScopes() |
hasGrantedAnyScope() |
Zastąp stare nowymi |
GoogleUser.isSignedIn() |
Usuń | |
GoogleUser.reloadAuthResponse() |
requestAccessToken() |
Usuń stary, wywołaj nowy, aby zastąpić wygasły lub unieważniony token dostępu. |
Obiekt gapi.auth2 i powiązane metody: |
||
gapi.auth2.AuthorizeConfig obiekt |
TokenClientConfig lub CodeClientConfig |
Zastąp stare nowymi |
gapi.auth2.AuthorizeResponse obiekt |
Usuń | |
gapi.auth2.AuthResponse obiekt |
Usuń | |
gapi.auth2.authorize() |
requestCode() lub requestAccessToken() |
Zastąp stare nowymi |
gapi.auth2.ClientConfig() |
TokenClientConfig lub CodeClientConfig |
Zastąp stare nowymi |
gapi.auth2.getAuthInstance() |
Usuń | |
gapi.auth2.init() |
initTokenClient() lub initCodeClient() |
Zastąp stare nowymi |
gapi.auth2.OfflineAccessOptions obiekt |
Usuń | |
gapi.auth2.SignInOptions obiekt |
Usuń | |
Obiekt gapi.signin2 i powiązane metody: |
||
gapi.signin2.render() |
Usuń. Wczytanie elementu g_id_signin w HTML DOM lub wywołanie JS google.accounts.id.renderButton powoduje zalogowanie użytkownika na konto Google. |
Przykładowe dane logowania
Istniejące dane logowania
Biblioteka platformy Logowanie przez Google, biblioteka klienta interfejsów API Google dla JavaScriptu i bezpośrednie wywołania punktów końcowych Google OAuth 2.0 zwracają w jednej odpowiedzi zarówno token dostępu OAuth 2.0, jak i token identyfikatora OpenID Connect.
Przykładowa odpowiedź zawierająca zarówno 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 Google Identity Services
Biblioteka Google Identity Services zwraca:
token dostępu, gdy jest 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" }lub token identyfikacji, gdy jest 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ź od Google podczas próby wysłania żądania do interfejsu API za pomocą 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"
}
}