W tym dokumencie wyjaśniono, jak aplikacje serwera WWW używają bibliotek klienta interfejsów API Google lub punktów końcowych Google OAuth 2.0 do implementacji autoryzacji OAuth 2.0 w celu uzyskania dostępu do interfejsów API Google.
Protokół OAuth 2.0 umożliwia użytkownikom udostępnianie określonych danych aplikacji przy jednoczesnym zachowaniu poufności nazw, haseł i innych informacji. Na przykład aplikacja może używać protokołu OAuth 2.0, aby uzyskać od użytkowników uprawnienia do przechowywania plików na ich Dyskach Google.
Ten przepływ OAuth 2.0 służy do autoryzacji użytkowników. Jest przeznaczony dla aplikacji, które mogą przechowywać informacje poufne i zachowywać stan. Prawidłowo autoryzowana aplikacja serwera WWW może uzyskać dostęp do interfejsu API, gdy użytkownik korzysta z aplikacji lub po jej opuszczeniu.
Aplikacje serwera WWW często używają też kont usługi do autoryzowania żądań do interfejsu API, zwłaszcza podczas wywoływania interfejsów Cloud API w celu uzyskania dostępu do danych opartych na projekcie, a nie do danych użytkownika. Aplikacje serwera WWW mogą używać kont usługi w połączeniu z autoryzacją użytkownika.
Biblioteki klienta
Przykłady w poszczególnych językach na tej stronie używają bibliotek klienta interfejsów API Google do implementacji autoryzacji OAuth 2.0. Aby uruchomić przykładowy kod, musisz najpierw zainstalować bibliotekę klienta dla swojego języka.
Gdy używasz biblioteki klienta interfejsu API Google do obsługi przepływu OAuth 2.0 w aplikacji, biblioteka klienta wykonuje wiele działań, które w przeciwnym razie aplikacja musiałaby obsłużyć samodzielnie. Określa na przykład, kiedy aplikacja może używać lub odświeżać przechowywane tokeny dostępu, a także kiedy musi ponownie uzyskać zgodę. Biblioteka klienta generuje też prawidłowe adresy URL przekierowań i pomaga we wdrażaniu modułów obsługi przekierowań, które wymieniają kody autoryzacji na tokeny dostępu.
Biblioteki klienta interfejsów API Google dla aplikacji po stronie serwera są dostępne w tych językach:
Wymagania wstępne
Włączanie interfejsów API w projekcie
Każda aplikacja, która wywołuje interfejsy API Google, musi je włączyć w Konsoli interfejsów API.
Aby włączyć interfejs API w projekcie:
- Otwórz Bibliotekę interfejsów API w Konsoli interfejsów API Google.
- Jeśli pojawi się taka prośba, wybierz projekt lub utwórz nowy.
- Biblioteka interfejsów API zawiera listę wszystkich dostępnych interfejsów API pogrupowanych według rodziny usług i popularności. Jeśli interfejs API, który chcesz włączyć, nie jest widoczny na liście, wyszukaj go lub kliknij Wyświetl wszystkie w rodzinie usług, do której należy.
- Wybierz interfejs API, który chcesz włączyć, a następnie kliknij przycisk Włącz.
- Jeśli pojawi się taka prośba, włącz płatności.
- Jeśli pojawi się taka prośba, przeczytaj i zaakceptuj Warunki korzystania z interfejsu API.
Tworzenie danych uwierzytelniających
Każda aplikacja, która używa protokołu OAuth 2.0 do uzyskiwania dostępu do interfejsów API Google, musi mieć dane uwierzytelniające, które identyfikują ją na serwerze OAuth 2.0 Google. Poniżej znajdziesz instrukcje tworzenia danych logowania do projektu. Twoje aplikacje mogą następnie używać tych danych logowania, aby uzyskiwać dostęp do interfejsów API, które zostały włączone w tym projekcie.
- Otwórz stronę Klienci.
- Kliknij Utwórz klienta.
- Wybierz typ aplikacji Aplikacja internetowa.
- Wypełnij formularz i kliknij Utwórz. Aplikacje, które używają języków i platform takich jak PHP, Java, Python, Ruby i .NET, muszą określać autoryzowane identyfikatory URI przekierowania. Identyfikatory URI przekierowania to punkty końcowe, do których serwer OAuth 2.0 może wysyłać odpowiedzi. Te punkty końcowe muszą być zgodne z regułami weryfikacji Google.
Do celów testowych możesz podać identyfikatory URI, które odnoszą się do komputera lokalnego, np.
http://localhost:8080. We wszystkich przykładach w tym dokumencie jako identyfikator URI przekierowania używany jesthttp://localhost:8080.Zalecamy zaprojektowanie punktów końcowych uwierzytelniania aplikacji w taki sposób, aby aplikacja nie ujawniała kodów autoryzacji innym zasobom na stronie.
Po utworzeniu danych logowania pobierz plik client_secret.json z konsoli interfejsów API. Zapisz plik w bezpiecznym miejscu, do którego dostęp ma tylko Twoja aplikacja.
Identyfikowanie zakresów dostępu
Zakresy umożliwiają aplikacji żądanie dostępu tylko do tych zasobów, których potrzebuje, a użytkownikom – kontrolowanie zakresu dostępu, który przyznają aplikacji. W związku z tym może istnieć odwrotna zależność między liczbą żądanych zakresów a prawdopodobieństwem uzyskania zgody użytkownika.
Zanim zaczniesz wdrażać autoryzację OAuth 2.0, zalecamy określenie zakresów, do których aplikacja będzie potrzebować uprawnień dostępu.
Zalecamy też, aby aplikacja prosiła o dostęp do zakresów autoryzacji w ramach procesu autoryzacji stopniowej, w którym aplikacja prosi o dostęp do danych użytkownika w odpowiednim kontekście. Dzięki temu użytkownicy łatwiej zrozumieją, dlaczego Twoja aplikacja potrzebuje dostępu, o który prosi.
Dokument Zakresy interfejsu OAuth 2.0 API zawiera pełną listę zakresów, których możesz używać do uzyskiwania dostępu do interfejsów API Google.
Wymagania dotyczące języka
Aby uruchomić dowolny przykładowy kod z tego dokumentu, musisz mieć konto Google, dostęp do internetu i przeglądarkę. Jeśli używasz jednej z bibliotek klienta interfejsu API, zapoznaj się też z wymaganiami dotyczącymi poszczególnych języków w sekcjach poniżej.
PHP
Aby uruchomić przykładowy kod PHP z tego dokumentu, musisz mieć:
- PHP w wersji 8.0 lub nowszej z zainstalowanym interfejsem wiersza poleceń (CLI) i rozszerzeniem JSON.
- Narzędzie do zarządzania zależnościami Composer.
-
Biblioteka klienta interfejsów API Google dla języka PHP:
composer require google/apiclient:^2.15.0
Więcej informacji znajdziesz w bibliotece klienta interfejsów API Google dla języka PHP.
Python
Aby uruchomić przykładowy kod w Pythonie podany w tym dokumencie, musisz mieć:
- Python 3.7 lub nowszy,
- Narzędzie do zarządzania pakietami pip.
- Biblioteka klienta interfejsów API Google dla Pythona w wersji 2.0:
pip install --upgrade google-api-python-client
google-auth,google-auth-oauthlibigoogle-auth-httplib2na potrzeby autoryzacji użytkownika.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- Platforma do tworzenia aplikacji internetowych Flask Python.
pip install --upgrade flask
- Biblioteka HTTP
requests.pip install --upgrade requests
Jeśli nie możesz uaktualnić Pythona i powiązanego przewodnika po migracji, zapoznaj się z informacjami o wersji biblioteki klienta interfejsu API Google dla Pythona.
Ruby
Aby uruchomić przykładowy kod w języku Ruby podany w tym dokumencie, musisz mieć:
- Ruby w wersji 2.6 lub nowszej
-
Biblioteka Google Auth Library dla języka Ruby:
gem install googleauth
-
Biblioteki klienta interfejsów API Google Dysku i Kalendarza:
gem install google-apis-drive_v3 google-apis-calendar_v3
-
Platforma do tworzenia aplikacji internetowych Sinatra Ruby.
gem install sinatra
Node.js
Aby uruchomić przykładowy kod w Node.js w tym dokumencie, potrzebujesz:
- Wersja LTS w trybie konserwacji, aktywna wersja LTS lub bieżąca wersja Node.js.
-
Klient interfejsów API Google w Node.js:
npm install googleapis crypto express express-session
HTTP/REST
Nie musisz instalować żadnych bibliotek, aby bezpośrednio wywoływać punkty końcowe protokołu OAuth 2.0.
Uzyskiwanie tokenów dostępu OAuth 2.0
Poniżej opisujemy, jak aplikacja współdziała z serwerem OAuth 2.0 Google, aby uzyskać zgodę użytkownika na wysłanie żądania do interfejsu API w jego imieniu. Twoja aplikacja musi uzyskać tę zgodę, zanim będzie mogła wykonać żądanie do interfejsu API Google, które wymaga autoryzacji użytkownika.
Lista poniżej zawiera podsumowanie tych kroków:
- Aplikacja określa uprawnienia, których potrzebuje.
- Aplikacja przekierowuje użytkownika do Google wraz z listą żądanych uprawnień.
- Użytkownik decyduje, czy przyznać uprawnienia Twojej aplikacji.
- Aplikacja dowiaduje się, jaką decyzję podjął użytkownik.
- Jeśli użytkownik przyznał wymagane uprawnienia, aplikacja pobiera tokeny potrzebne do wysyłania żądań do interfejsu API w imieniu użytkownika.
Krok 1. Skonfiguruj parametry autoryzacji
Pierwszym krokiem jest utworzenie prośby o autoryzację. To żądanie ustawia parametry, które identyfikują aplikację i określają uprawnienia, o które użytkownik zostanie poproszony.
- Jeśli do uwierzytelniania i autoryzacji OAuth 2.0 używasz biblioteki klienta Google, utwórz i skonfiguruj obiekt, który definiuje te parametry.
- Jeśli wywołasz bezpośrednio punkt końcowy Google OAuth 2.0, wygenerujesz adres URL i ustawisz w nim parametry.
Na kartach poniżej znajdziesz obsługiwane parametry autoryzacji aplikacji serwera WWW. Przykłady w poszczególnych językach pokazują też, jak używać biblioteki klienta lub biblioteki autoryzacji do konfigurowania obiektu, który ustawia te parametry:
PHP
Poniższy fragment kodu tworzy obiekt Google\Client(), który definiuje parametry w żądaniu autoryzacji.
Ten obiekt używa informacji z pliku client_secret.json do identyfikacji aplikacji. (Więcej informacji o tym pliku znajdziesz w artykule o tworzeniu danych uwierzytelniających). Obiekt identyfikuje też zakresy, do których aplikacja prosi o dostęp, oraz adres URL punktu końcowego autoryzacji aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0 Google. Na koniec kod ustawia opcjonalne parametry access_type i include_granted_scopes.
Na przykład ten kod żąda dostępu tylko do odczytu i dostępu offline do metadanych Dysku Google i wydarzeń w Kalendarzu użytkownika:
use Google\Client; $client = new Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfig('client_secret.json'); // Required, to set the scope value, call the addScope function $client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Python
Poniższy fragment kodu używa modułu google-auth-oauthlib.flow do utworzenia żądania autoryzacji.
Kod tworzy obiekt Flow, który identyfikuje aplikację za pomocą informacji z pliku client_secret.json pobranego po utworzeniu danych uwierzytelniających. Ten obiekt określa też zakresy, do których aplikacja prosi o dostęp, oraz adres URL punktu końcowego uwierzytelniania aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0 Google. Na koniec kod ustawia opcjonalne parametry access_type i include_granted_scopes.
Na przykład ten kod żąda dostępu tylko do odczytu i dostępu offline do metadanych Dysku Google i wydarzeń w Kalendarzu użytkownika:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file('client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly']) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = 'https://www.example.com/oauth2callback' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. authorization_url, state = flow.authorization_url( # Recommended, enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Optional, enable incremental authorization. Recommended as a best practice. include_granted_scopes='true', # Optional, if your application knows which user is trying to authenticate, it can use this # parameter to provide a hint to the Google Authentication Server. login_hint='hint@example.com', # Optional, set prompt to 'consent' will prompt the user for consent prompt='consent')
Ruby
Użyj utworzonego pliku client_secrets.json, aby skonfigurować obiekt klienta w aplikacji. Podczas konfigurowania obiektu klienta określasz zakresy, do których aplikacja potrzebuje dostępu, oraz adres URL punktu końcowego uwierzytelniania aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0.
Na przykład ten kod żąda dostępu tylko do odczytu i dostępu offline do metadanych Dysku Google i wydarzeń w Kalendarzu użytkownika:
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. callback_uri = '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, callback_uri)
Aplikacja używa obiektu klienta do wykonywania operacji OAuth 2.0, takich jak generowanie adresów URL żądań autoryzacji i stosowanie tokenów dostępu do żądań HTTP.
Node.js
Poniższy fragment kodu tworzy obiekt google.auth.OAuth2, który definiuje parametry w żądaniu autoryzacji.
Ten obiekt używa informacji z pliku client_secret.json do identyfikacji aplikacji. Aby poprosić użytkownika o uprawnienia do pobrania tokena dostępu, przekieruj go na stronę zgody. Aby utworzyć adres URL strony z prośbą o zgodę:
const {google} = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI * from the client_secret.json file. To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly' ]; // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state });
Ważna uwaga – parametr refresh_token jest zwracany tylko przy pierwszej autoryzacji. Więcej informacji znajdziesz
tutaj.
HTTP/REST
Punkt końcowy OAuth 2.0 Google znajduje się pod adresem https://accounts.google.com/o/oauth2/v2/auth. Ten punkt końcowy jest dostępny tylko przez HTTPS. Zwykłe połączenia HTTP są odrzucane.
Serwer autoryzacji Google obsługuje te parametry ciągu zapytania w przypadku aplikacji serwera WWW:
| Parametry | |||||||
|---|---|---|---|---|---|---|---|
client_id |
Wymagany
Identyfikator klienta aplikacji. Tę wartość znajdziesz na stronie Klienci w konsoli Cloud. |
||||||
redirect_uri |
Wymagany
Określa, gdzie serwer interfejsu API przekierowuje użytkownika po zakończeniu procesu autoryzacji. Wartość musi dokładnie odpowiadać jednemu z autoryzowanych identyfikatorów URI przekierowania klienta OAuth 2.0, które zostały skonfigurowane na stronie Klienci w konsoli Cloud klienta. Jeśli ta wartość nie jest zgodna z autoryzowanym identyfikatorem URI przekierowania dla podanego Pamiętaj, że schemat |
||||||
response_type |
Wymagany
Określa, czy punkt końcowy Google OAuth 2.0 zwraca kod autoryzacji. W przypadku aplikacji serwera WWW ustaw wartość parametru na |
||||||
scope |
Wymagany
Rozdzielona spacjami lista zakresów, które identyfikują zasoby, do których aplikacja może uzyskać dostęp w imieniu użytkownika. Te wartości są przekazywane do ekranu zgody, który Google wyświetla użytkownikowi. Zakresy umożliwiają aplikacji żądanie dostępu tylko do tych zasobów, których potrzebuje, a użytkownikom – kontrolowanie zakresu dostępu, który przyznają aplikacji. Istnieje więc odwrotna zależność między liczbą żądanych zakresów a prawdopodobieństwem uzyskania zgody użytkownika. Zalecamy, aby aplikacja prosiła o dostęp do zakresów autoryzacji w kontekście, gdy tylko jest to możliwe. Jeśli poprosisz o dostęp do danych użytkownika w odpowiednim kontekście, korzystając z autoryzacji stopniowej, użytkownicy będą rozumieć, do czego aplikacja potrzebuje konkretnych danych. |
||||||
access_type |
Zalecane
Wskazuje, czy aplikacja może odświeżać tokeny dostępu, gdy użytkownik nie korzysta z przeglądarki. Prawidłowe wartości parametru to Ustaw wartość |
||||||
state |
Zalecane
Określa dowolną wartość ciągu, której aplikacja używa do utrzymania stanu między żądaniem autoryzacji a odpowiedzią serwera autoryzacji.
Serwer zwraca dokładną wartość, którą wysyłasz jako parę Możesz używać tego parametru do różnych celów, np. do kierowania użytkownika do odpowiedniego zasobu w aplikacji, wysyłania liczb jednorazowych i ograniczania ryzyka sfałszowania żądania z innej witryny. Ponieważ wartość |
||||||
include_granted_scopes |
Opcjonalny
Umożliwia aplikacjom korzystanie z autoryzacji przyrostowej w celu żądania dostępu do dodatkowych zakresów w kontekście. Jeśli ustawisz wartość tego parametru na |
||||||
enable_granular_consent |
Opcjonalny
Domyślna wartość to Gdy Google włączy uprawnienia szczegółowe dla aplikacji, ten parametr nie będzie już działać. |
||||||
login_hint |
Opcjonalny
Jeśli Twoja aplikacja wie, który użytkownik próbuje się uwierzytelnić, może użyć tego parametru, aby przekazać podpowiedź serwerowi uwierzytelniania Google. Serwer używa wskazówki, aby uprościć proces logowania, wstępnie wypełniając pole z adresem e-mail w formularzu logowania lub wybierając odpowiednią sesję wielokrotnego logowania. Ustaw wartość parametru na adres e-mail lub identyfikator |
||||||
prompt |
Opcjonalny
Rozdzielana spacjami lista promptów, które mają być wyświetlane użytkownikowi, z uwzględnieniem wielkości liter. Jeśli nie określisz tego parametru, użytkownik zostanie poproszony o wyrażenie zgody tylko wtedy, gdy Twój projekt po raz pierwszy poprosi o dostęp. Więcej informacji znajdziesz w sekcji Prośba o ponowne wyrażenie zgody. Możliwe wartości to:
|
||||||
Krok 2. Przekieruj do serwera OAuth 2.0 Google
Przekieruj użytkownika na serwer OAuth 2.0 Google, aby rozpocząć proces uwierzytelniania i autoryzacji. Zwykle dzieje się tak, gdy aplikacja po raz pierwszy potrzebuje dostępu do danych użytkownika. W przypadku autoryzacji przyrostowej ten krok ma miejsce również wtedy, gdy aplikacja po raz pierwszy potrzebuje dostępu do dodatkowych zasobów, do których nie ma uprawnień.
PHP
- Wygeneruj adres URL, aby poprosić o dostęp z serwera OAuth 2.0 Google:
$auth_url = $client->createAuthUrl(); - Przekieruj użytkownika do
$auth_url:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
Ten przykład pokazuje, jak przekierować użytkownika na adres URL autoryzacji za pomocą platformy aplikacji internetowych Flask:
return flask.redirect(authorization_url)
Ruby
- Wygeneruj adres URL, aby poprosić o dostęp z serwera OAuth 2.0 Google:
auth_uri = authorizer.get_authorization_url(request: request)
- Przekieruj użytkownika na stronę
auth_uri.
Node.js
-
Aby poprosić o dostęp z serwera OAuth 2.0 Google, użyj adresu URL
authorizationUrlwygenerowanego w kroku 1generateAuthUrl. -
Przekieruj użytkownika na stronę
authorizationUrl.res.redirect(authorizationUrl);
HTTP/REST
Przykładowe przekierowanie na serwer autoryzacji Google
Poniżej znajduje się przykładowy adres URL z podziałami wierszy i spacjami, które ułatwiają czytanie.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//developers.google.com/oauthplayground& client_id=client_id
Po utworzeniu adresu URL żądania przekieruj na niego użytkownika.
Serwer OAuth 2.0 Google uwierzytelnia użytkownika i uzyskuje od niego zgodę na dostęp aplikacji do żądanych zakresów. Odpowiedź jest wysyłana z powrotem do aplikacji za pomocą podanego przez Ciebie adresu URL przekierowania.
Krok 3. Google prosi użytkownika o zgodę
W tym kroku użytkownik decyduje, czy przyznać aplikacji żądany dostęp. Na tym etapie Google wyświetla okno zgody, które zawiera nazwę aplikacji i interfejsy API Google, do których aplikacja prosi o dostęp, oraz dane uwierzytelniające użytkownika i podsumowanie zakresów dostępu, które zostaną przyznane. Użytkownik może wtedy wyrazić zgodę na przyznanie dostępu do co najmniej 1 zakresu, o który prosi aplikacja, lub odrzucić prośbę.
Na tym etapie aplikacja nie musi nic robić, ponieważ czeka na odpowiedź z serwera OAuth 2.0 Google, która wskazuje, czy dostęp został przyznany. Odpowiedź została wyjaśniona w następnym kroku.
Błędy
Żądania wysyłane do punktu końcowego autoryzacji OAuth 2.0 Google mogą wyświetlać komunikaty o błędach dla użytkownika zamiast oczekiwanych procesów uwierzytelniania i autoryzacji. Typowe kody błędów i sugerowane rozwiązania:
admin_policy_enforced
Konto Google nie może autoryzować co najmniej jednego żądanego zakresu ze względu na zasady administratora Google Workspace. Więcej informacji o tym, jak administrator może ograniczyć dostęp do wszystkich zakresów lub zakresów poufnych i ograniczonych, dopóki nie zostanie on wyraźnie przyznany Twojemu identyfikatorowi klienta OAuth, znajdziesz w artykule pomocy dla administratorów Google Workspace Określanie, które aplikacje innych firm i aplikacje wewnętrzne mają dostęp do danych Google Workspace.
disallowed_useragent
Punkt końcowy autoryzacji jest wyświetlany w ramach wbudowanego klienta użytkownika, który jest niedozwolony przez zasady Google dotyczące protokołu OAuth 2.0.
Deweloperzy aplikacji na iOS i macOS mogą napotkać ten błąd podczas otwierania żądań autoryzacji w WKWebView.
Deweloperzy powinni zamiast tego używać bibliotek iOS, takich jak Logowanie przez Google na iOS lub AppAuth na iOS od OpenID Foundation.
Twórcy stron internetowych mogą napotkać ten błąd, gdy aplikacja na iOS lub macOS otwiera ogólny link internetowy we wbudowanym kliencie użytkownika, a użytkownik przechodzi z Twojej witryny do punktu końcowego autoryzacji OAuth 2.0 Google. Deweloperzy powinni zezwalać na otwieranie ogólnych linków w domyślnym module obsługi linków systemu operacyjnego, który obejmuje zarówno moduły obsługi uniwersalnych linków, jak i domyślną aplikację przeglądarki. Obsługiwana jest też biblioteka SFSafariViewController.
org_internal
Identyfikator klienta OAuth w żądaniu jest częścią projektu, który ogranicza dostęp do kont Google w określonej organizacji Google Cloud. Więcej informacji o tej opcji konfiguracji znajdziesz w sekcji Typ użytkownika w artykule pomocy dotyczącym konfigurowania ekranu zgody OAuth.
invalid_client
Tajny klucz klienta OAuth jest nieprawidłowy. Sprawdź konfigurację klienta OAuth, w tym identyfikator klienta i tajny klucz użyte w tym żądaniu.
deleted_client
Klient OAuth używany do wysyłania żądania został usunięty. Usuwanie może odbywać się ręcznie lub automatycznie w przypadku nieużywanych klientów . Usuniętych klientów można przywrócić w ciągu 30 dni od usunięcia. Więcej informacji
invalid_grant
Podczas odświeżania tokena dostępu lub korzystania z autoryzacji przyrostowej token mógł wygasnąć lub zostać unieważniony. Ponownie uwierzytelnij użytkownika i poproś go o zgodę użytkownika na uzyskanie nowych tokenów. Jeśli ten błąd nadal występuje, sprawdź, czy aplikacja została prawidłowo skonfigurowana i czy w żądaniu używasz prawidłowych tokenów i parametrów. W przeciwnym razie konto użytkownika mogło zostać usunięte lub wyłączone.
redirect_uri_mismatch
Wartość redirect_uri przekazana w żądaniu autoryzacji nie jest zgodna z autoryzowanym identyfikatorem URI przekierowania dla identyfikatora klienta OAuth. Sprawdź autoryzowane identyfikatory URI przekierowania na stronie Klienty w konsoli Google Cloud.
Parametr redirect_uri może odnosić się do przepływu OAuth poza pasmem (OOB), który został wycofany i nie jest już obsługiwany. Aby zaktualizować integrację, zapoznaj się z przewodnikiem po migracji.
invalid_request
Wystąpił błąd w Twoim żądaniu. Może to wynikać z kilku powodów:
- Żądanie nie zostało prawidłowo sformatowane.
- W żądaniu brakowało wymaganych parametrów.
- Żądanie używa metody autoryzacji, której Google nie obsługuje. Sprawdź, czy integracja OAuth korzysta z zalecanej metody integracji
Krok 4. Przetwórz odpowiedź serwera OAuth 2.0
Serwer OAuth 2.0 odpowiada na żądanie dostępu aplikacji, używając adresu URL podanego w żądaniu.
Jeśli użytkownik zatwierdzi prośbę o dostęp, odpowiedź będzie zawierać kod autoryzacji. Jeśli użytkownik nie zatwierdzi prośby, odpowiedź będzie zawierać komunikat o błędzie. Kod autoryzacji lub komunikat o błędzie zwracany do serwera WWW pojawia się w ciągu zapytania, jak w tych przykładach:
Odpowiedź błędu:
https://oauth2.example.com/auth?error=access_denied
Odpowiedź z kodem autoryzacji:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
Przykładowa odpowiedź serwera OAuth 2.0
Możesz przetestować ten proces, klikając ten przykładowy adres URL, który żąda dostępu tylko do odczytu do metadanych plików na Dysku Google i do wydarzeń w Kalendarzu Google:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//developers.google.com/oauthplayground& client_id=client_id
Po zakończeniu przepływu OAuth 2.0 przeglądarka przekieruje Cię do OAuth 2.0 Playground, narzędzia do testowania przepływów OAuth. Zobaczysz, że OAuth 2.0 Playground automatycznie przechwycił kod autoryzacji.
Krok 5. Wymień kod autoryzacji na tokeny odświeżania i dostępu
Gdy serwer WWW otrzyma kod autoryzacji, może go wymienić na token dostępu.
PHP
Aby wymienić kod autoryzacji na token dostępu, użyj metody fetchAccessTokenWithAuthCode:
$access_token = $client->fetchAccessTokenWithAuthCode($_GET['code']);Python
Na stronie wywołania zwrotnego użyj biblioteki google-auth, aby zweryfikować odpowiedź serwera autoryzacji. Następnie użyj metody flow.fetch_token, aby wymienić kod autoryzacji w tej odpowiedzi na token dostępu:
state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in browser session storage, but for security: client_id, client_secret, # and token_uri are instead stored only on the backend server. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'granted_scopes': credentials.granted_scopes}
Ruby
Na stronie wywołania zwrotnego użyj biblioteki googleauth, aby zweryfikować odpowiedź serwera autoryzacji. Użyj metody authorizer.handle_auth_callback_deferred, aby zapisać kod autoryzacji i przekierować użytkownika z powrotem do adresu URL, który pierwotnie zażądał autoryzacji. Spowoduje to odroczenie wymiany kodu przez tymczasowe zapisanie wyników w sesji użytkownika.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
Aby wymienić kod autoryzacji na token dostępu, użyj metody getToken:
const url = require('url'); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); });
HTTP/REST
Aby wymienić kod autoryzacji na token dostępu, wywołaj punkt końcowy https://oauth2.googleapis.com/token i ustaw te parametry:
| Pola | |
|---|---|
client_id |
Identyfikator klienta uzyskany na stronie Klienci w konsoli Cloud. |
client_secret |
Opcjonalny
Tajny klucz klienta uzyskany na stronie Klienci w konsoli Cloud. |
code |
Kod autoryzacji zwrócony w odpowiedzi na początkowe żądanie. |
grant_type |
Zgodnie ze specyfikacją OAuth 2.0 wartość tego pola musi być ustawiona na authorization_code. |
redirect_uri |
Jeden z identyfikatorów URI przekierowania wymienionych dla Twojego projektu na stronie Klienci w konsoli Cloud dla danego client_id. |
Chociaż użycie DPoP jest opcjonalne, zalecamy je w celu zwiększenia bezpieczeństwa. Bezpieczeństwo DPoP zależy od tego, czy klucz prywatny jest ograniczony do jednego urządzenia. Zalecamy przechowywanie go w sposób uniemożliwiający skopiowanie go poza urządzenie, na przykład przy użyciu modułów TPM, bezpiecznych enklaw lub innych magazynów kluczy obsługiwanych sprzętowo. Aby korzystać z DPoP, aplikacja musi wygenerować nowy, unikalny token JWT potwierdzający DPoP dla każdego żądania do punktu końcowego tokena i dodać go jako nagłówek żądania HTTP.
| Nagłówek | Wymagane | Opis |
|---|---|---|
DPoP |
Opcjonalny | Dowód DPoP to token JWT, który potwierdza posiadanie klucza prywatnego. To jest nagłówek, a nie parametr. Jeśli go podasz, zwrócone tokeny zostaną powiązane z tym kluczem. Dla każdego żądania należy wygenerować nowy, unikalny dowód, który musi zawierać oświadczenia htm (metoda HTTP) i htu (identyfikator URI HTTP) pasujące do żądania. |
Poniższy fragment kodu pokazuje przykładowe żądanie:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\ VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\ nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\ QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\ oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\ WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\ 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your_client_id& redirect_uri=https%3A//developers.google.com/oauthplayground& grant_type=authorization_code
Tworzenie dowodu DPoP
Poniżej opisujemy, jak utworzyć dowód DPoP za pomocą OpenSSL z wiersza poleceń:
- Wygeneruj parę kluczy EC P-256:
openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem openssl ec -in dpop_private.pem -pubout -out dpop_public.pem
- Utwórz nagłówek DPoP:
Nagłówek musi zawierać oświadczenia
typ,algijwk(klucz publiczny). Wartościxiyto współrzędne klucza publicznego EC zakodowane w formacie Base64Url. Zakoduj ten obiekt JSON w formacie Base64Url:{ "typ":"dpop+jwt", "alg":"ES256", "jwk": { "kty":"EC", "x":"YOUR_PUBLIC_KEY_X", "y":"YOUR_PUBLIC_KEY_Y", "crv":"P-256" } } - Utwórz ładunek DPoP:
Ładunek musi zawierać
jti(unikalny identyfikator żądania),htm(metoda HTTP, np.POST),htu(identyfikator URI HTTP, np.https://oauth2.googleapis.com/token) iiat(czas wydania). Jeśli w odpowiedzi na poprzednie żądanie serwer przesłał liczbę jednorazową w nagłówkuDPoP-Nonce, musisz uwzględnić tę wartość w deklaracjinonce. Deklaracja liczby jednorazowej jest opcjonalna w przypadku wymiany kodów autoryzacji i jest używana tylko wtedy, gdy wcześniej otrzymano nagłówek DPoP-Nonce. Zakoduj ten obiekt JSON w formacie Base64Url:{ "jti":"JTI_VALUE", "htm":"POST", "htu":"https://oauth2.googleapis.com/token", "iat":YOUR_JWT_ISSUED_TIME, "nonce":"SERVER_PROVIDED_NONCE" }Wartość
jtizależy od typu giełdy:- W przypadku wymiany kodów autoryzacji parametr
jtimusi być zakodowanym w formacie Base64Url skrótem SHA256 kodu autoryzacji:"jti":"BASE64URL(SHA256(AUTHORIZATION_CODE))". - W przypadku wymiany tokenów odświeżania parametr
jtimusi być unikalnym identyfikatorem żądania:"jti":"YOUR_UNIQUE_PER_REQUEST_IDENTIFIER".
- W przypadku wymiany kodów autoryzacji parametr
- Podpisywanie dowodu:
Połącz zakodowany nagłówek i ładunek, używając kropki (
.), a następnie podpisz wynik kluczem prywatnym za pomocą algorytmu ES256. Pamiętaj, że JWS wymaga, aby podpis był w nieprzetworzonym formacie połączonymR | S(64 bajty dla P-256). Jeśli używasz bezpośrednio OpenSSL, musisz przekonwertować domyślny podpis zakodowany w formacie ASN.1 DER na ten format nieprzetworzony.
Pomyślna wymiana jest sygnalizowana odpowiedzią 200 OK zawierającą tokeny. Jeśli podczas wymiany zostanie użyty prawidłowy dowód DPoP, token odświeżania zwrócony przez Google będzie powiązany z Twoim kluczem za pomocą DPoP, ale tokeny dostępu nie będą powiązane z DPoP. Tokeny dostępu zachowają token_type Bearer, a nie DPoP.
Dodatkowo Google zwraca w odpowiedzi nagłówek HTTP DPoP-Nonce.
Klient musi zapisać tę liczbę jednorazową w pamięci podręcznej i uwzględnić ją w oświadczeniu nonce dowodu DPoP w kolejnych żądaniach (np. podczas wymiany tokena odświeżania na nowy token dostępu lub wywoływania interfejsów API chronionych przez DPoP). Używając tej wcześniej wydanej liczby jednorazowej, możesz uniknąć dodatkowego błędu komunikacji (use_dpop_nonce) przy następnym żądaniu.
W przypadku żądań wymiany tokenów wysyłanych z tokenami odświeżania powiązanymi z DPoP należy dołączyć dowody DPoP.
Nieudana wymiana ma miejsce, gdy nagłówek DPoP jest nieobecny, mimo że jest oczekiwany, jest nieprawidłowy lub gdy dowód używa innego klucza niż ten powiązany z tokenem. W takich przypadkach serwer zwraca błąd 400 Bad Request.
Jeśli dowód DPoP zawiera niezgodne deklaracje htm lub htu, wygasłą deklarację iat, ponownie użytą deklarację jti lub nieprawidłowy podpis, Google zwraca kod błędu invalid_dpop_proof.
Jeśli wymagana jest liczba jednorazowa DPoP, np.podczas wymiany tokena odświeżania, a w dowodzie DPoP brakuje deklaracji nonce lub wartość liczby jednorazowej jest nieakceptowalna dla serwera (np. wygasła, została już użyta lub jest nieprawidłowa), Google zwraca kod błędu use_dpop_nonce wraz z nagłówkiem HTTP DPoP-Nonce zawierającym nową liczbę jednorazową, której możesz użyć w kolejnym żądaniu.
Inne błędy mogą zwracać invalid_grant.
Google odpowiada na to żądanie, zwracając obiekt JSON zawierający krótkotrwały token dostępu i token odświeżania.
Pamiętaj, że token odświeżania jest zwracany tylko wtedy, gdy aplikacja ustawi parametr access_type na offline w początkowym żądaniu wysłanym do serwera autoryzacji Google.
Odpowiedź zawiera te pola:
| Pola | |
|---|---|
access_token |
Token wysyłany przez aplikację w celu autoryzacji żądania do interfejsu API Google. |
expires_in |
Pozostały czas ważności tokena dostępu w sekundach. |
refresh_token |
Token, którego możesz użyć do uzyskania nowego tokena dostępu. Tokeny odświeżania są ważne, dopóki użytkownik nie unieważni dostępu lub token odświeżania nie wygaśnie. Jeśli użyto DPoP, token odświeżania jest powiązany z kluczem prywatnym użytym do podpisania dowodu DPoP.
To pole jest obecne w odpowiedzi tylko wtedy, gdy w początkowym żądaniu wysłanym do serwera autoryzacji Google parametr access_type został ustawiony na offline.
|
refresh_token_expires_in |
Pozostały czas ważności tokena odświeżania w sekundach. Ta wartość jest ustawiana tylko wtedy, gdy użytkownik przyzna dostęp na określony czas. |
scope |
Zakresy dostępu przyznane przez access_token, wyrażone jako lista ciągów znaków rozdzielonych spacjami, z uwzględnieniem wielkości liter. |
token_type |
Typ zwracanego tokena. Ta wartość zawsze wynosi Bearer, nawet gdy używany jest DPoP. |
Poniższy fragment kodu pokazuje przykładowe nagłówki odpowiedzi i treść, gdy używany jest protokół DPoP:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"token_type": "Bearer",
"scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
"refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}Błędy
Podczas wymiany kodu autoryzacji na token dostępu zamiast oczekiwanej odpowiedzi może pojawić się ten błąd. W tej sekcji znajdziesz typowe kody błędów i sugerowane rozwiązania.
invalid_grant
Podany kod autoryzacji jest nieprawidłowy lub ma nieprawidłowy format. Poproś o nowy kod, ponownie uruchamiając proces OAuth, aby jeszcze raz poprosić użytkownika o zgodę.
Krok 6. Sprawdź, które zakresy przyznali użytkownicy
Jeśli poprosisz o kilka uprawnień (zakresów), użytkownicy mogą nie przyznać aplikacji dostępu do wszystkich z nich. Aplikacja musi sprawdzić, które zakresy zostały faktycznie przyznane, i odpowiednio obsłużyć sytuacje, w których niektóre uprawnienia zostały odrzucone, zwykle przez wyłączenie funkcji, które korzystają z tych odrzuconych zakresów.
Są jednak wyjątki. Aplikacje Google Workspace Enterprise z przekazywaniem uprawnień dostępu w całej domenie lub aplikacje oznaczone jako zaufane pomijają ekran zgody na uprawnienia szczegółowe. W przypadku tych aplikacji użytkownicy nie zobaczą ekranu zgody na szczegółowe uprawnienia. Zamiast tego aplikacja otrzyma wszystkie żądane zakresy lub żadne.
Więcej informacji znajdziesz w artykule Jak postępować z uprawnieniami szczegółowymi.
PHP
Aby sprawdzić, które zakresy zostały przyznane przez użytkownika, użyj metody getGrantedScope():
// Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ];
Python
Zwrócony obiekt credentials ma właściwość granted_scopes, która jest listą zakresów przyznanych aplikacji przez użytkownika.
credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'granted_scopes': credentials.granted_scopes}
Ta funkcja sprawdza, które zakresy użytkownik przyznał Twojej aplikacji.
def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features
Ruby
Jeśli prosisz o kilka zakresów naraz, sprawdź, które z nich zostały przyznane, za pomocą właściwości scope obiektu credentials.
# User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Calling the APIs, etc else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end
Node.js
Jeśli prosisz o kilka zakresów naraz, sprawdź, które z nich zostały przyznane, za pomocą właściwości scope obiektu tokens.
// User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // Calling the APIs, etc. } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly }
HTTP/REST
Aby sprawdzić, czy użytkownik przyznał aplikacji dostęp do określonego zakresu, sprawdź pole scope w odpowiedzi tokena dostępu. Zakresy dostępu przyznane przez parametr access_token, wyrażone jako lista ciągów znaków rozdzielonych spacjami, z uwzględnieniem wielkości liter.
Na przykład ta przykładowa odpowiedź z tokenem dostępu wskazuje, że użytkownik przyznał aplikacji uprawnienia do odczytu aktywności na Dysku i wydarzeń w Kalendarzu:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
Wywoływanie interfejsów API Google
PHP
Aby użyć tokena dostępu do wywołania interfejsów API Google, wykonaj te czynności:
- Jeśli chcesz zastosować token dostępu do nowego obiektu
Google\Client– na przykład jeśli token dostępu został zapisany w sesji użytkownika – użyj metodysetAccessToken:$client->setAccessToken($access_token); - Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzy się, przekazując autoryzowany obiekt
Google\Clientdo konstruktora interfejsu API, który chcesz wywołać. Aby na przykład wywołać interfejs Drive API:$drive = new Google\Service\Drive($client); - Wysyłaj żądania do usługi interfejsu API za pomocą
interfejsu udostępnianego przez obiekt usługi.
Aby na przykład wyświetlić listę plików na Dysku Google uwierzytelnionego użytkownika:
$files = $drive->files->listFiles(array());
Python
Po uzyskaniu tokena dostępu aplikacja może go używać do autoryzowania żądań do interfejsu API w imieniu danego konta użytkownika lub konta usługi. Użyj danych uwierzytelniających użytkownika, aby utworzyć obiekt usługi dla interfejsu API, który chcesz wywołać, a następnie użyj tego obiektu do wysyłania autoryzowanych żądań do interfejsu API.
- Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzysz, wywołując metodę
buildbibliotekigoogleapiclient.discoveryz nazwą i wersją interfejsu API oraz danymi logowania użytkownika: Aby na przykład wywołać wersję 3 interfejsu Drive API:from googleapiclient.discovery import build drive = build('drive', 'v2', credentials=credentials)
- Wysyłaj żądania do usługi interfejsu API, korzystając z interfejsu udostępnianego przez obiekt usługi.
Aby na przykład wyświetlić listę plików na Dysku Google uwierzytelnionego użytkownika:
files = drive.files().list().execute()
Ruby
Po uzyskaniu tokena dostępu aplikacja może go używać do wysyłania żądań do interfejsu API w imieniu danego konta użytkownika lub konta usługi. Użyj danych uwierzytelniających użytkownika, aby utworzyć obiekt usługi dla interfejsu API, który chcesz wywołać, a następnie użyj tego obiektu do wysyłania autoryzowanych żądań do interfejsu API.
- Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać.
Aby na przykład wywołać wersję 3 interfejsu Drive API:
drive = Google::Apis::DriveV3::DriveService.new
- Ustaw dane logowania w usłudze:
drive.authorization = credentials
- Wysyłaj żądania do usługi interfejsu API za pomocą interfejsu udostępnianego przez obiekt usługi.
Aby na przykład wyświetlić listę plików na Dysku Google uwierzytelnionego użytkownika:
files = drive.list_files
Możesz też autoryzować poszczególne metody, podając parametr options:
files = drive.list_files(options: { authorization: credentials })
Node.js
Po uzyskaniu tokena dostępu i ustawieniu go w obiekcie OAuth2 użyj tego obiektu do wywoływania interfejsów API Google. Aplikacja może używać tego tokena do autoryzowania żądań do interfejsu API w imieniu danego konta użytkownika lub konta usługi. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać.
Na przykład ten kod używa interfejsu Google Drive API do wyświetlania nazw plików na Dysku użytkownika.
const { google } = require('googleapis'); // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } });
HTTP/REST
Gdy aplikacja uzyska token dostępu, możesz go używać do wywoływania interfejsu API Google w imieniu danego konta użytkownika, jeśli przyznano zakresy dostępu wymagane przez interfejs API. Aby to zrobić, dołącz token dostępu do żądania do interfejsu API, podając parametr zapytania access_token lub wartość Bearer nagłówka HTTP Authorization. Jeśli to możliwe, lepiej używać nagłówka HTTP, ponieważ ciągi zapytań są zwykle widoczne w logach serwera. W większości przypadków możesz użyć biblioteki klienta, aby skonfigurować wywołania interfejsów API Google (na przykład podczas wywoływania interfejsu Drive Files API).
Możesz wypróbować wszystkie interfejsy API Google i wyświetlić ich zakresy w OAuth 2.0 Playground.
Przykłady HTTP GET
Wywołanie punktu końcowego
drive.files (interfejs Drive Files API) za pomocą nagłówka HTTP Authorization: Bearer może wyglądać tak: Pamiętaj, że musisz podać własny token dostępu:
GET /drive/v2/files HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
Oto wywołanie tego samego interfejsu API dla uwierzytelnionego użytkownika z użyciem parametru ciągu zapytania access_token:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
curl przykładu
Możesz przetestować te polecenia za pomocą aplikacji wiersza poleceń curl. Oto przykład użycia opcji nagłówka HTTP (preferowanej):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files
Możesz też użyć parametru ciągu zapytania:
curl https://www.googleapis.com/drive/v2/files?access_token=access_token
Kompletny przykład
Poniższy przykład drukuje listę plików w formacie JSON na Dysku Google użytkownika po uwierzytelnieniu i wyrażeniu zgody na dostęp aplikacji do metadanych Dysku użytkownika.
PHP
Aby uruchomić ten przykład:
- W Konsoli interfejsów API dodaj adres URL komputera lokalnego do listy adresów URL przekierowań. Na przykład dodaj
http://localhost:8080. - Utwórz nowy katalog i przejdź do niego. Na przykład:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Zainstaluj bibliotekę klienta interfejsu API Google dla języka PHP za pomocą Composera:
composer require google/apiclient:^2.15.0
- Utwórz pliki
index.phpioauth2callback.phpz tą zawartością. - Uruchom przykład z wbudowanym serwerem WWW PHP do testów:
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secret.json'); // User granted permission as an access token is in the session. if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); // Check if user granted Drive permission if ($_SESSION['granted_scopes_dict']['Drive']) { echo "Drive feature is enabled."; echo "</br>"; $drive = new Drive($client); $files = array(); $response = $drive->files->listFiles(array()); foreach ($response->files as $file) { echo "File: " . $file->name . " (" . $file->id . ")"; echo "</br>"; } } else { echo "Drive feature is NOT enabled."; echo "</br>"; } // Check if user granted Calendar permission if ($_SESSION['granted_scopes_dict']['Calendar']) { echo "Calendar feature is enabled."; echo "</br>"; } else { echo "Calendar feature is NOT enabled."; echo "</br>"; } } else { // Redirect users to outh2call.php which redirects users to Google OAuth 2.0 $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } ?>
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfigFile('client_secret.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF']); // Required, to set the scope value, call the addScope function. $client->addScope([Google\Service\Drive::DRIVE_METADATA_READONLY, Google\Service\Calendar::CALENDAR_READONLY]); // Enable incremental authorization. Recommended as a best practice. $client->setIncludeGrantedScopes(true); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType("offline"); // Generate a URL for authorization as it doesn't contain code and error if (!isset($_GET['code']) && !isset($_GET['error'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; // Generate a url that asks permissions. $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } // User authorized the request and authorization code is returned to exchange access and // refresh tokens. if (isset($_GET['code'])) { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } // Get access and refresh tokens (if access_type is offline) $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); /** Save access and refresh token to the session variables. * ACTION ITEM: In a production app, you likely want to save the * refresh token in a secure persistent storage instead. */ $_SESSION['access_token'] = $token; $_SESSION['refresh_token'] = $client->getRefreshToken(); // Space-separated string of granted scopes if it exists, otherwise null. $granted_scopes = $client->getOAuth2Service()->getGrantedScope(); // Determine which scopes user granted and build a dictionary $granted_scopes_dict = [ 'Drive' => str_contains($granted_scopes, Google\Service\Drive::DRIVE_METADATA_READONLY), 'Calendar' => str_contains($granted_scopes, Google\Service\Calendar::CALENDAR_READONLY) ]; $_SESSION['granted_scopes_dict'] = $granted_scopes_dict; $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); } // An error response e.g. error=access_denied if (isset($_GET['error'])) { echo "Error: ". $_GET['error']; } ?>
Python
W tym przykładzie używamy platformy Flask. Uruchamia aplikację internetową pod adresem http://localhost:8080, która umożliwia przetestowanie przepływu OAuth 2.0. Po przejściu na ten adres URL powinno pojawić się 5 linków:
- Call Drive API (Wywołaj interfejs Drive API): ten link prowadzi do strony, która próbuje wykonać przykładowe żądanie do interfejsu API, jeśli użytkownicy przyznali uprawnienia. W razie potrzeby uruchamia proces autoryzacji. Jeśli operacja się powiedzie, na stronie wyświetli się odpowiedź interfejsu API.
- Przykładowa strona do wywoływania interfejsu Calendar API: ten link prowadzi do przykładowej strony, która próbuje wykonać przykładowe żądanie do interfejsu Calendar API, jeśli użytkownicy przyznali uprawnienia. W razie potrzeby rozpoczyna proces autoryzacji. Jeśli operacja się powiedzie, na stronie wyświetli się odpowiedź interfejsu API.
- Przetestuj bezpośrednio proces autoryzacji: ten link prowadzi do strony, która próbuje przeprowadzić użytkownika przez proces autoryzacji. Aplikacja prosi o uprawnienia do przesyłania autoryzowanych żądań do interfejsu API w imieniu użytkownika.
- Unieważnij bieżące dane logowania: ten link prowadzi do strony, na której można unieważnić uprawnienia, które użytkownik już przyznał aplikacji.
- Wyczyść dane logowania sesji Flask: ten link usuwa dane logowania autoryzacji przechowywane w sesji Flask. Dzięki temu zobaczysz, co się stanie, gdy użytkownik, który już przyznał uprawnienia Twojej aplikacji, spróbuje wykonać żądanie do interfejsu API w nowej sesji. Możesz też zobaczyć odpowiedź interfejsu API, którą otrzymałaby Twoja aplikacja, gdyby użytkownik wycofał uprawnienia przyznane aplikacji, a aplikacja nadal próbowała autoryzować żądanie za pomocą unieważnionego tokena dostępu.
# -*- coding: utf-8 -*- import os import flask import json import requests import google.oauth2.credentials import google_auth_oauthlib.flow import googleapiclient.discovery # This variable specifies the name of a file that contains the OAuth 2.0 # information for this application, including its client_id and client_secret. CLIENT_SECRETS_FILE = "client_secret.json" # The OAuth 2.0 access scope allows for access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly'] API_SERVICE_NAME = 'drive' API_VERSION = 'v2' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/drive') def drive_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['drive']: # Load client secrets from the server-side file. with open(CLIENT_SECRETS_FILE, 'r') as f: client_config = json.load(f)['web'] # Load user-specific credentials from browser session storage. session_credentials = flask.session['credentials'] # Reconstruct the credentials object. credentials = google.oauth2.credentials.Credentials( refresh_token=session_credentials.get('refresh_token'), scopes=session_credentials.get('granted_scopes'), token=session_credentials.get('token'), client_id=client_config.get('client_id'), client_secret=client_config.get('client_secret'), token_uri=client_config.get('token_uri')) drive = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) files = drive.files().list().execute() # Save credentials back to session in case access token was refreshed. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**files) else: # User didn't authorize read-only Drive activity permission. return '<p>Drive feature is not enabled.</p>' @app.route('/calendar') def calendar_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') features = flask.session['features'] if features['calendar']: # User authorized Calendar read permission. # Calling the APIs, etc. return ('<p>User granted the Google Calendar read permission. '+ 'This sample code does not include code to call Calendar</p>') else: # User didn't authorize Calendar read permission. # Update UX and application accordingly return '<p>Calendar feature is not enabled.</p>' @app.route('/authorize') def authorize(): # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES) # The URI created here must exactly match one of the authorized redirect URIs # for the OAuth 2.0 client, which you configured in the API Console. If this # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch' # error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true') # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) @app.route('/oauth2callback') def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials credentials = credentials_to_dict(credentials) flask.session['credentials'] = credentials # Check which scopes user granted features = check_granted_scopes(credentials) flask.session['features'] = features return flask.redirect('/') @app.route('/revoke') def revoke(): if 'credentials' not in flask.session: return ('You need to <a href="/authorize">authorize</a> before ' + 'testing the code to revoke credentials.') # Load client secrets from the server-side file. with open(CLIENT_SECRETS_FILE, 'r') as f: client_config = json.load(f)['web'] # Load user-specific credentials from the session. session_credentials = flask.session['credentials'] # Reconstruct the credentials object. credentials = google.oauth2.credentials.Credentials( refresh_token=session_credentials.get('refresh_token'), scopes=session_credentials.get('granted_scopes'), token=session_credentials.get('token'), client_id=client_config.get('client_id'), client_secret=client_config.get('client_secret'), token_uri=client_config.get('token_uri')) revoke = requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'}) status_code = getattr(revoke, 'status_code') if status_code == 200: # Clear the user's session credentials after successful revocation if 'credentials' in flask.session: del flask.session['credentials'] del flask.session['features'] return('Credentials successfully revoked.' + print_index_table()) else: return('An error occurred.' + print_index_table()) @app.route('/clear') def clear_credentials(): if 'credentials' in flask.session: del flask.session['credentials'] return ('Credentials have been cleared.<br><br>' + print_index_table()) def credentials_to_dict(credentials): return {'token': credentials.token, 'refresh_token': credentials.refresh_token, 'granted_scopes': credentials.granted_scopes} def check_granted_scopes(credentials): features = {} if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['granted_scopes']: features['drive'] = True else: features['drive'] = False if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['granted_scopes']: features['calendar'] = True else: features['calendar'] = False return features def print_index_table(): return ('<table>' + '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' + '<td>Go directly to the authorization flow. If there are stored ' + ' credentials, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/drive">Call Drive API directly</a></td>' + '<td> Use stored credentials to call the API, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/calendar">Call Calendar API directly</a></td>' + '<td> Use stored credentials to call the API, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/revoke">Revoke current credentials</a></td>' + '<td>Revoke the access token associated with the current user ' + ' session. After revoking credentials, if you go to the test ' + ' page, you should see an <code>invalid_grant</code> error.' + '</td></tr>' + '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' + '<td>Clear the access token currently stored in the user session. ' + ' After clearing the token, if you <a href="/authorize">authorize</a> ' + ' again, you should go back to the auth flow.' + '</td></tr></table>') if __name__ == '__main__': # When running locally, disable OAuthlib's HTTPs verification. # ACTION ITEM for developers: # When running in production *do not* leave this option enabled. os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # This disables the requested scopes and granted scopes check. # If users only grant partial request, the warning would not be thrown. os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1' # Specify a hostname and port that are set as a valid redirect URI # for your API project in the Google API Console. app.run('localhost', 8080, debug=True)
Ruby
W tym przykładzie używamy platformy Sinatra.
require 'googleauth' require 'googleauth/web_user_authorizer' require 'googleauth/stores/redis_token_store' require 'google/apis/drive_v3' require 'google/apis/calendar_v3' require 'sinatra' configure do enable :sessions # Required, call the from_file method to retrieve the client ID from a # client_secret.json file. set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') # Required, scope value # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. scope = ['Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY', 'Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY'] # Required, Authorizers require a storage instance to manage long term persistence of # access and refresh tokens. set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. set :callback_uri, '/oauth2callback' # To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI # from the client_secret.json file. To get these credentials for your application, visit # https://console.cloud.google.com/apis/credentials. set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, callback_uri: settings.callback_uri) end get '/' do # NOTE: Assumes the user is already authenticated to the app user_id = request.session['user_id'] # Fetch stored credentials for the user from the given request session. # nil if none present credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? # Generate a url that asks the user to authorize requested scope(s). # Then, redirect user to the url. redirect settings.authorizer.get_authorization_url(request: request) end # User authorized the request. Now, check which scopes were granted. if credentials.scope.include?(Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY) # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. drive = Google::Apis::DriveV3::DriveService.new files = drive.list_files(options: { authorization: credentials }) "<pre>#{JSON.pretty_generate(files.to_h)}</pre>" else # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly end # Check if user authorized Calendar read permission. if credentials.scope.include?(Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY) # User authorized Calendar read permission. # Calling the APIs, etc. else # User didn't authorize Calendar read permission. # Update UX and application accordingly end end # Receive the callback from Google's OAuth 2.0 server. get '/oauth2callback' do # Handle the result of the oauth callback. Defers the exchange of the code by # temporarily stashing the results in the user's session. target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
Aby uruchomić ten przykład:
-
W Konsoli interfejsów API dodaj adres URL komputera lokalnego do listy adresów URL przekierowań. Na przykład dodaj
http://localhost. - Upewnij się, że masz zainstalowaną wersję Node.js LTS w trybie konserwacji, aktywną wersję LTS lub bieżącą wersję.
-
Utwórz nowy katalog i przejdź do niego. Na przykład:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
Zainstaluj bibliotekę klienta interfejsu API Google dla Node.js za pomocą npm:
npm install googleapis
-
Utwórz pliki
main.jsz tą zawartością. -
Uruchom przykład:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/calendar.readonly' ]; /* Global variable that stores user credential in this code example. * ACTION ITEM for developers: * Store user's refresh token in your data store if * incorporating this code into your real app. * For more information on handling refresh tokens, * see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens */ let userCredential = null; async function main() { const app = express(); app.use(session({ secret: 'your_secure_secret_key', // Replace with a strong secret resave: false, saveUninitialized: false, })); // Example on redirecting user to Google's OAuth 2.0 server. app.get('/', async (req, res) => { // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity and Google Calendar scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state }); res.redirect(authorizationUrl); }); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); /** Save credential to the global variable in case access token was refreshed. * ACTION ITEM: In a production app, you likely want to save the refresh token * in a secure persistent database instead. */ userCredential = tokens; // User authorized the request. Now, check which scopes were granted. if (tokens.scope.includes('https://www.googleapis.com/auth/drive.metadata.readonly')) { // User authorized read-only Drive activity permission. // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } }); } else { // User didn't authorize read-only Drive activity permission. // Update UX and application accordingly } // Check if user authorized Calendar read permission. if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly')) { // User authorized Calendar read permission. // Calling the APIs, etc. } else { // User didn't authorize Calendar read permission. // Update UX and application accordingly } } }); // Example on revoking a token app.get('/revoke', async (req, res) => { // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end(); }); const server = http.createServer(app); server.listen(8080); } main().catch(console.error);
HTTP/REST
Ten przykład w Pythonie używa platformy Flask i biblioteki Requests, aby zademonstrować proces OAuth 2.0 w internecie. W tym przypadku zalecamy użycie biblioteki klienta interfejsu API Google dla języka Python. (Przykład na karcie Python korzysta z biblioteki klienta).
import json import flask import requests app = flask.Flask(__name__) # To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit # https://console.cloud.google.com/apis/credentials. CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app # Access scopes for two non-Sign-In scopes: Read-only Drive activity and Google Calendar. SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly' # Indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. REDIRECT_URI = 'http://example.com/oauth2callback' @app.route('/') def index(): if 'credentials' not in flask.session: return flask.redirect(flask.url_for('oauth2callback')) credentials = json.loads(flask.session['credentials']) if credentials['expires_in'] <= 0: return flask.redirect(flask.url_for('oauth2callback')) else: # User authorized the request. Now, check which scopes were granted. if 'https://www.googleapis.com/auth/drive.metadata.readonly' in credentials['scope']: # User authorized read-only Drive activity permission. # Example of using Google Drive API to list filenames in user's Drive. headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/drive/v2/files' r = requests.get(req_uri, headers=headers).text else: # User didn't authorize read-only Drive activity permission. # Update UX and application accordingly r = 'User did not authorize Drive permission.' # Check if user authorized Calendar read permission. if 'https://www.googleapis.com/auth/calendar.readonly' in credentials['scope']: # User authorized Calendar read permission. # Calling the APIs, etc. r += 'User authorized Calendar permission.' else: # User didn't authorize Calendar read permission. # Update UX and application accordingly r += 'User did not authorize Calendar permission.' return r @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state # Generate a url that asks permissions for the Drive activity # and Google Calendar scope. Then, redirect user to the url. auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI, SCOPE, state) return flask.redirect(auth_uri) else: if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']: return 'State mismatch. Possible CSRF attack.', 400 auth_code = flask.request.args.get('code') data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'} # Exchange authorization code for access and refresh tokens (if access_type is offline) r = requests.post('https://oauth2.googleapis.com/token', data=data) flask.session['credentials'] = r.text return flask.redirect(flask.url_for('index')) if __name__ == '__main__': import uuid app.secret_key = str(uuid.uuid4()) app.debug = False app.run()
Reguły weryfikacji identyfikatora URI przekierowania
Google stosuje te reguły weryfikacji do identyfikatorów URI przekierowania, aby pomóc deweloperom w zapewnieniu bezpieczeństwa aplikacji. Identyfikatory URI przekierowania muszą być zgodne z tymi regułami. Definicje domeny, hosta, ścieżki, zapytania, schematu i informacji o użytkowniku, które są używane w tych regułach, znajdziesz w sekcji 3 dokumentu RFC 3986.
| Reguły weryfikacji | |
|---|---|
| Schemat |
Identyfikatory URI przekierowania muszą używać schematu HTTPS, a nie zwykłego HTTP. Identyfikatory URI hosta lokalnego (w tym identyfikatory URI adresów IP hosta lokalnego) są wyłączone z tej reguły. |
| Osoba prowadząca |
Hosty nie mogą być nieprzetworzonymi adresami IP. Adresy IP hosta lokalnego są wyłączone z tej reguły. |
| Domena |
“googleusercontent.com”.goo.gl), chyba że aplikacja jest właścicielem domeny. Ponadto, jeśli aplikacja, która jest właścicielem domeny skracającej, zdecyduje się przekierować do tej domeny, identyfikator URI przekierowania musi zawierać “/google-callback/” w ścieżce lub kończyć się ciągiem “/google-callback”. |
| Userinfo |
Identyfikatory URI przekierowania nie mogą zawierać komponentu podrzędnego userinfo. |
| Ścieżka |
Identyfikatory URI przekierowania nie mogą zawierać znaków przemierzania ścieżki (nazywanego też cofaniem się w katalogu), które są reprezentowane przez |
| Zapytanie |
Identyfikatory URI przekierowania nie mogą zawierać otwartych przekierowań. |
| Fragment |
Identyfikatory URI przekierowania nie mogą zawierać komponentu fragmentu. |
| Znaki |
Identyfikatory URI przekierowania nie mogą zawierać niektórych znaków, takich jak:
|
Autoryzacja przyrostowa
W protokole OAuth 2.0 aplikacja prosi o autoryzację dostępu do zasobów, które są identyfikowane przez zakresy. Zgodnie ze sprawdzonymi metodami dotyczącymi wygody użytkowników najlepiej jest prosić o autoryzację zasobów w momencie, gdy są one potrzebne. Aby umożliwić takie działanie, serwer autoryzacji Google obsługuje autoryzację przyrostową. Ta funkcja umożliwia wysyłanie żądań o zakresy, gdy są one potrzebne. Jeśli użytkownik przyzna uprawnienia do nowego zakresu, zwraca kod autoryzacji, który można wymienić na token zawierający wszystkie zakresy, które użytkownik przyznał projektowi.
Na przykład aplikacja, która umożliwia użytkownikom odsłuchiwanie próbek utworów muzycznych i tworzenie miksów, może wymagać bardzo niewielu zasobów podczas logowania, być może tylko imienia i nazwiska osoby logującej się. Jednak zapisanie gotowego miksu wymagałoby dostępu do Dysku Google. Większość osób uznałaby za naturalne, gdyby prośba o dostęp do Dysku Google pojawiała się tylko wtedy, gdy aplikacja faktycznie go potrzebuje.
W takim przypadku podczas logowania aplikacja może poprosić o zakresy openid i profile, aby przeprowadzić podstawowe logowanie, a później, przy pierwszym żądaniu zapisania miksu, o zakres https://www.googleapis.com/auth/drive.file.
Aby wdrożyć autoryzację przyrostową, wykonaj normalny proces żądania tokena dostępu, ale upewnij się, że żądanie autoryzacji zawiera wcześniej przyznane zakresy. Dzięki temu aplikacja nie musi zarządzać wieloma tokenami dostępu.
W przypadku tokena dostępu uzyskanego w ramach autoryzacji przyrostowej obowiązują te reguły:
- Tokena można używać do uzyskiwania dostępu do zasobów odpowiadających dowolnemu zakresowi uwzględnionemu w nowej, połączonej autoryzacji.
- Gdy używasz tokena odświeżania do uzyskania tokena dostępu, token dostępu reprezentuje połączone uprawnienia i może być używany w przypadku dowolnej wartości
scopezawartej w odpowiedzi. - Połączona autoryzacja obejmuje wszystkie zakresy, które użytkownik przyznał projektowi interfejsu API, nawet jeśli uprawnienia zostały zażądane przez różnych klientów. Jeśli na przykład użytkownik przyznał dostęp do jednego zakresu za pomocą klienta aplikacji na komputery, a następnie przyznał dostęp do innego zakresu tej samej aplikacji za pomocą klienta mobilnego, połączona autoryzacja będzie obejmować oba zakresy.
- Jeśli unieważnisz token reprezentujący autoryzację łączoną, dostęp do wszystkich zakresów tej autoryzacji w imieniu powiązanego użytkownika zostanie unieważniony jednocześnie.
Przykładowe kody w różnych językach w sekcji Krok 1. Skonfiguruj przekierowanie autoryzacji na serwer OAuth 2.0 Google korzystają z autoryzacji przyrostowej. Poniższe przykłady kodu pokazują też kod, który należy dodać, aby używać autoryzacji przyrostowej.
PHP
$client->setIncludeGrantedScopes(true);Python
W Pythonie ustaw argument słowa kluczowego include_granted_scopes na true, aby mieć pewność, że żądanie autoryzacji obejmuje wcześniej przyznane zakresy. Jest bardzo prawdopodobne, że include_granted_scopes nie będzie jedynym ustawionym argumentem słowa kluczowego, jak pokazano w przykładzie poniżej.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Ruby
auth_client.update!( :additional_parameters => {"include_granted_scopes" => "true"} )
Node.js
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
HTTP/REST
GET https://accounts.google.com/o/oauth2/v2/auth? client_id=your_client_id& response_type=code& state=state_parameter_passthrough_value& scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly& redirect_uri=https%3A//developers.google.com/oauthplayground& prompt=consent& include_granted_scopes=true
Odświeżanie tokena dostępu (dostęp offline)
Tokeny dostępu okresowo wygasają i stają się nieprawidłowymi danymi logowania dla powiązanego żądania do interfejsu API. Możesz odświeżyć token dostępu bez proszenia użytkownika o zgodę (nawet jeśli użytkownik nie jest obecny), jeśli poprosisz o dostęp offline do zakresów powiązanych z tokenem.
- Jeśli używasz biblioteki klienta interfejsu API Google, obiekt klienta odświeża token dostępu w razie potrzeby, o ile skonfigurujesz ten obiekt pod kątem dostępu offline.
- Jeśli nie używasz biblioteki klienta, musisz ustawić parametr zapytania HTTP
access_typenaofflinepodczas przekierowywania użytkownika na serwer OAuth 2.0 Google. W takim przypadku serwer autoryzacji Google zwraca token odświeżania, gdy wymieniasz kod autoryzacji na token dostępu. Jeśli token dostępu wygaśnie (lub w dowolnym innym momencie), możesz użyć tokena odświeżania, aby uzyskać nowy token dostępu.
Żądanie dostępu offline jest wymagane w przypadku każdej aplikacji, która musi uzyskać dostęp do interfejsu API Google, gdy użytkownik nie jest obecny. Na przykład aplikacja, która wykonuje usługi kopii zapasowej lub działania w określonych godzinach, musi mieć możliwość odświeżenia tokena dostępu, gdy użytkownik nie jest obecny. Domyślny styl dostępu to online.
Aplikacje internetowe po stronie serwera, zainstalowane aplikacje i urządzenia uzyskują tokeny odświeżania podczas procesu autoryzacji. Tokeny odświeżania nie są zwykle używane w aplikacjach internetowych po stronie klienta (JavaScript).
PHP
Jeśli aplikacja potrzebuje dostępu offline do interfejsu API Google, ustaw typ dostępu klienta API na offline:
$client->setAccessType("offline");Gdy użytkownik przyzna dostęp offline do żądanych zakresów, możesz nadal używać klienta interfejsu API, aby uzyskiwać dostęp do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta odświeży token dostępu w razie potrzeby.
Python
W Pythonie ustaw argument słowa kluczowego access_type na offline, aby mieć pewność, że będziesz mieć możliwość odświeżenia tokena dostępu bez konieczności ponownego proszenia użytkownika o uprawnienia. Jest bardzo prawdopodobne, że access_type nie będzie jedynym ustawionym argumentem słowa kluczowego, jak w przykładzie poniżej.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Gdy użytkownik przyzna dostęp offline do żądanych zakresów, możesz nadal używać klienta interfejsu API, aby uzyskiwać dostęp do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta odświeży token dostępu w razie potrzeby.
Ruby
Jeśli aplikacja potrzebuje dostępu offline do interfejsu API Google, ustaw typ dostępu klienta API na offline:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
Gdy użytkownik przyzna dostęp offline do żądanych zakresów, możesz nadal używać klienta interfejsu API, aby uzyskiwać dostęp do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta odświeży token dostępu w razie potrzeby.
Node.js
Jeśli aplikacja potrzebuje dostępu offline do interfejsu API Google, ustaw typ dostępu klienta API na offline:
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
Gdy użytkownik przyzna dostęp offline do żądanych zakresów, możesz nadal używać klienta interfejsu API, aby uzyskiwać dostęp do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta odświeży token dostępu w razie potrzeby.
Tokeny dostępu wygasają. Ta biblioteka automatycznie użyje tokena odświeżania, aby uzyskać nowy token dostępu, jeśli ten zbliża się do daty ważności. Najprostszym sposobem na upewnienie się, że zawsze przechowujesz najnowsze tokeny, jest użycie zdarzenia tokenów:
oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // store the refresh_token in your secure persistent database console.log(tokens.refresh_token); } console.log(tokens.access_token); });
To zdarzenie tokenów występuje tylko podczas pierwszej autoryzacji. Aby otrzymać token odświeżania, musisz ustawić parametr access_type na offline podczas wywoływania metody generateAuthUrl. Jeśli aplikacja ma już wymagane uprawnienia, ale nie ustawiono odpowiednich ograniczeń dotyczących otrzymywania tokena odświeżania, musisz ponownie autoryzować aplikację, aby otrzymać nowy token odświeżania.
Aby ustawić refresh_token później, możesz użyć metody setCredentials:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
Gdy klient otrzyma token odświeżania, tokeny dostępu będą automatycznie uzyskiwane i odświeżane przy następnym wywołaniu interfejsu API.
HTTP/REST
Aby odświeżyć token dostępu, aplikacja wysyła do serwera autoryzacji Google (https://oauth2.googleapis.com/token) żądanie HTTPS POST, które zawiera w treści te parametry:
| Nazwa | Wartość |
|---|---|
client_id |
Identyfikator klienta uzyskany z Konsoli interfejsów API. |
client_secret |
Opcjonalny
Tajny klucz klienta uzyskany z Konsoli interfejsów API. |
grant_type |
Zgodnie z definicją w specyfikacji OAuth 2.0 wartość tego pola musi być ustawiona na refresh_token. |
refresh_token |
Token odświeżania zwrócony z wymiany kodu autoryzacji. |
Chociaż użycie DPoP jest opcjonalne, zalecamy je w celu zwiększenia bezpieczeństwa. Aby używać DPoP z tokenem odświeżania, aplikacja musi wygenerować nowy, unikalny token JWT potwierdzający DPoP dla każdego żądania wysyłanego do punktu końcowego tokena. To potwierdzenie musi być podpisane tym samym kluczem prywatnym, który został użyty podczas początkowej wymiany kodu autoryzacji. Aplikacja dodaje dowód jako nagłówek żądania HTTP.
| Nagłówek | Wymagane | Opis |
|---|---|---|
DPoP |
Opcjonalny | Dowód DPoP to token JWT, który potwierdza posiadanie klucza prywatnego. To jest nagłówek, a nie parametr. Jeśli go podasz, zwrócone tokeny zostaną powiązane z tym kluczem. Dla każdego żądania należy wygenerować nowy, unikalny dowód, który musi zawierać oświadczenia htm (metoda HTTP) i htu (identyfikator URI HTTP) pasujące do żądania. |
Poniższy fragment kodu pokazuje przykładowe żądanie:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded DPoP: DPOP_PROOF_JWT client_id=your_client_id& refresh_token=refresh_token& grant_type=refresh_token
Aby używać DPoP z tokenem odświeżania, musisz wygenerować nowy, unikalny token JWT potwierdzenia DPoP dla żądania. Szczegółowe instrukcje generowania pary kluczy i tworzenia tokena JWT znajdziesz w sekcji Tworzenie dowodu DPoP.
Pomyślna wymiana jest sygnalizowana odpowiedzią 200 OK zawierającą nowy token dostępu. Gdy używany jest protokół DPoP, token_type to Bearer. Odpowiedź z powodzeniem potwierdza, że dowód DPoP dla tokena odświeżania został zaakceptowany. Google może też zwrócić w odpowiedzi nowy nagłówek HTTP DPoP-Nonce. Jeśli zostanie zwrócony, klient musi zapisać tę liczbę jednorazową w pamięci podręcznej i uwzględnić ją w oświadczeniu nonce dowodu DPoP w kolejnych żądaniach.
Nieudana wymiana ma miejsce, gdy brakuje nagłówka DPoP, jest on nieprawidłowy lub używa nieprawidłowego klucza. Szczegółowe informacje o konkretnych kodach błędów DPoP i obsłudze liczb jednorazowych znajdziesz w sekcji Nieudana wymiana.
Poniższy fragment kodu pokazuje przykładowe nagłówki odpowiedzi i treść, gdy używany jest protokół DPoP:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
"token_type": "Bearer"
}Pamiętaj, że liczba tokenów odświeżania, które zostaną wydane, jest ograniczona. Istnieje limit na kombinację klient/użytkownik oraz limit na użytkownika we wszystkich klientach. Tokeny odświeżania należy zapisywać w pamięci długoterminowej i używać ich, dopóki są ważne. Jeśli aplikacja żąda zbyt wielu tokenów odświeżania, może przekroczyć te limity. W takim przypadku starsze tokeny odświeżania przestaną działać.
Unieważnienie tokena
W niektórych przypadkach użytkownik może chcieć anulować dostęp przyznany aplikacji. Użytkownik może anulować dostęp w ustawieniach konta. Więcej informacji znajdziesz w sekcji Usuwanie dostępu witryny lub aplikacji w dokumencie pomocy „Aplikacje i witryny innych firm mające dostęp do Twojego konta”.
Aplikacja może też programowo unieważnić przyznany jej dostęp. Programowe unieważnianie jest ważne w przypadkach, gdy użytkownik anuluje subskrypcję, usunie aplikację lub zasoby interfejsu API wymagane przez aplikację ulegną znacznej zmianie. Innymi słowy, część procesu usuwania może obejmować żądanie do interfejsu API, aby upewnić się, że uprawnienia wcześniej przyznane aplikacji zostały usunięte.
PHP
Aby unieważnić token automatycznie, wywołaj revokeToken():
$client->revokeToken();Python
Aby programowo unieważnić token, wyślij żądanie do https://oauth2.googleapis.com/revoke, które zawiera token jako parametr i ustawia nagłówek Content-Type:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Ruby
Aby programowo unieważnić token, wyślij żądanie HTTP do punktu końcowego oauth2.revoke:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania również zostanie unieważniony.
Jeśli unieważnienie zostanie przetworzone, kod stanu odpowiedzi będzie wynosił 200. W przypadku błędów zwracany jest kod stanu 400 wraz z kodem błędu.
Node.js
Aby programowo unieważnić token, wyślij żądanie HTTPS POST do punktu końcowego /revoke:
const https = require('https'); // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end();
Parametr tokena może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania również zostanie unieważniony.
Jeśli unieważnienie zostanie przetworzone, kod stanu odpowiedzi będzie wynosił 200. W przypadku błędów zwracany jest kod stanu 400 wraz z kodem błędu.
HTTP/REST
Aby programowo unieważnić token, aplikacja wysyła żądanie do https://oauth2.googleapis.com/revoke i dołącza token jako parametr:
curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
https://oauth2.googleapis.com/revoke?token={token}Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania również zostanie unieważniony.
Jeśli unieważnienie zostanie przetworzone, kod stanu HTTP odpowiedzi to 200. W przypadku błędów zwracany jest kod stanu HTTP 400 wraz z kodem błędu.
Dostęp zależny od czasu
Dostęp czasowy umożliwia użytkownikowi przyznanie aplikacji dostępu do jego danych na ograniczony czas w celu wykonania działania. Dostęp czasowy jest dostępny w wybranych usługach Google podczas procesu wyrażania zgody, co daje użytkownikom możliwość przyznania dostępu na ograniczony czas. Przykładem jest interfejs Data Portability API, który umożliwia jednorazowe przeniesienie danych.
Gdy użytkownik przyzna Twojej aplikacji dostęp na określony czas, token odświeżania wygaśnie po upływie tego czasu. Pamiętaj, że w pewnych okolicznościach tokeny odświeżania mogą zostać unieważnione wcześniej. Szczegółowe informacje znajdziesz w tych przypadkach. W takich przypadkach pole refresh_token_expires_in zwracane w odpowiedzi na wymianę kodu autoryzacji reprezentuje czas pozostały do wygaśnięcia tokena odświeżania.
Wdrażanie ochrony wszystkich kont
Dodatkowym krokiem, który należy podjąć, aby chronić konta użytkowników, jest wdrożenie ochrony wszystkich kont za pomocą usługi ochrony wszystkich kont Google. Ta usługa umożliwia subskrybowanie powiadomień o zdarzeniach związanych z bezpieczeństwem, które dostarczają aplikacji informacji o ważnych zmianach na koncie użytkownika. Możesz następnie wykorzystać te informacje, aby podjąć działania w zależności od tego, jak chcesz zareagować na zdarzenia.
Oto kilka przykładów typów zdarzeń wysyłanych do Twojej aplikacji przez usługę ochrony wszystkich kont Google:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked -
https://schemas.openid.net/secevent/oauth/event-type/token-revoked -
https://schemas.openid.net/secevent/risc/event-type/account-disabled
Więcej informacji o tym, jak wdrożyć ochronę wszystkich kont, oraz pełną listę dostępnych zdarzeń znajdziesz na stronie Chroń konta użytkowników za pomocą ochrony wszystkich kont .