Korzystanie z protokołu OAuth 2.0 w aplikacjach serwerowych

W tym dokumencie wyjaśniamy, jak aplikacje serwera internetowego używają bibliotek klienta interfejsu API Google lub punktów końcowych Google OAuth 2.0 do implementowania autoryzacji OAuth 2.0 w celu uzyskiwania dostępu do interfejsów API Google.

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 Dysku Google.

Ten przepływ OAuth 2.0 służy wyłącznie do autoryzacji użytkownika. Jest przeznaczony dla aplikacji, które mogą przechowywać informacje poufne i utrzymywać stan. Odpowiednio autoryzowana aplikacja serwera internetowego może uzyskać dostęp do interfejsu API, gdy użytkownik korzysta z aplikacji lub po tym, jak ją opuści.

Aplikacje serwera internetowego często używają też kont usług do autoryzowania żądań API, zwłaszcza podczas wywoływania interfejsów Cloud API w celu uzyskania dostępu do danych związanych z projektem, a nie danych konkretnego użytkownika. Aplikacje serwera internetowego 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 korzystają z bibliotek klienta interfejsów API Google do implementowania autoryzacji OAuth 2.0. Aby uruchomić przykładowy kod, musisz najpierw zainstalować bibliotekę klienta w wybranym języku.

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ługiwać samodzielnie. Określa na przykład, kiedy aplikacja może używać lub odświeżać zapisane tokeny dostępu, a także kiedy musi ponownie uzyskać zgodę użytkownika. Biblioteka klienta generuje też prawidłowe adresy URL przekierowania i pomaga wdrażać moduły 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 włączyć te interfejsy w  API Console.

Aby włączyć interfejs API w projekcie:

  1. Open the API Library w  Google API Console.
  2. If prompted, select a project, or create a new one.
  3. Zawiera ona listę wszystkich dostępnych interfejsów API pogrupowanych według rodziny usług i popularności. API Library Jeśli interfejs API, który chcesz włączyć, nie jest widoczny na liście, użyj wyszukiwarki, aby go znaleźć, lub kliknij Wyświetl wszystkie w grupie produktów, do której należy.
  4. Wybierz interfejs API, który chcesz włączyć, a następnie kliknij przycisk Włącz.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

Tworzenie danych uwierzytelniających

Każda aplikacja, która używa OAuth 2.0 do uzyskiwania dostępu do interfejsów API Google, musi mieć dane logowania autoryzacji, które identyfikują aplikację na serwerze OAuth 2.0 Google. Poniżej znajdziesz instrukcje tworzenia danych logowania do projektu. Aplikacje mogą następnie używać tych danych logowania do uzyskiwania dostępu do interfejsów API włączonych w tym projekcie.

  1. Go to the Credentials page.
  2. Kliknij Utwórz klienta.
  3. Wybierz typ aplikacji Aplikacja internetowa.
  4. 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 zasadami weryfikacji Google.

    Na potrzeby testów możesz podać identyfikatory URI odnoszące się do lokalnego komputera, np. http://localhost:8080. Pamiętaj, że we wszystkich przykładach w tym dokumencie jako identyfikator URI przekierowania użyto adresu http://localhost:8080.

    Zalecamy zaprojektowanie punktów końcowych uwierzytelniania aplikacji w taki sposób, aby aplikacja nie udostępniała kodów autoryzacji innym zasobom na stronie.

Po utworzeniu danych logowania pobierz plik client_secret.json z  API Console. Bezpiecznie przechowuj plik w lokalizacji, do której dostęp ma tylko Twoja aplikacja.

Określanie zakresów dostępu

Zakresy umożliwiają aplikacji żądanie dostępu tylko do potrzebnych jej zasobów, a użytkownikom – kontrolowanie zakresu dostępu przyznawanego aplikacji. Dlatego 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 Twoja aplikacja będzie potrzebować dostępu.

Zalecamy też, aby aplikacja prosiła o dostęp do zakresów autoryzacji w ramach procesu autoryzacji stopniowej, w którym żąda dostępu do danych użytkownika w odpowiednim kontekście. Dzięki temu użytkownicy łatwiej zrozumieją, dlaczego aplikacja potrzebuje dostępu, o który prosi.

Dokument Zakresy interfejsu API OAuth 2.0 zawiera pełną listę zakresów, których możesz używać do uzyskiwania dostępu do interfejsów API Google.

Wymagania dotyczące poszczególnych języków

Aby uruchomić dowolny z przykładowych kodów w tym dokumencie, 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, które znajdziesz poniżej.

PHP

Aby uruchomić przykładowy kod PHP w tym dokumencie, potrzebujesz:

  • PHP w wersji 8.0 lub nowszej z zainstalowanym interfejsem wiersza poleceń 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 artykule Biblioteka klienta interfejsów API Google dla języka PHP.

Python

Aby uruchomić przykładowy kod w Pythonie w tym dokumencie, potrzebujesz:

  • Python 3.7 lub nowszy
  • Narzędzie do zarządzania pakietami pip.
  • Wersja 2.0 biblioteki klienta interfejsów API Google dla języka Python:
    pip install --upgrade google-api-python-client
  • google-auth, google-auth-oauthlibgoogle-auth-httplib2 do autoryzacji użytkownika.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • Platforma Flask do tworzenia aplikacji internetowych w języku Python.
    pip install --upgrade flask
  • Biblioteka HTTP requests.
    pip install --upgrade requests

Jeśli nie możesz uaktualnić Pythona i powiązanego z nim przewodnika migracji, zapoznaj się z informacjami o wersji biblioteki klienta interfejsu API Google w Pythonie.

Ruby

Aby uruchomić przykładowy kod w Ruby w tym dokumencie, potrzebujesz:

  • 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 Node.js w trybie konserwacji LTS, aktywna wersja LTS lub bieżąca wersja.
  • Klient interfejsów API Google w Node.js:

    npm install googleapis crypto express express-session

HTTP/REST

Aby bezpośrednio wywoływać punkty końcowe OAuth 2.0, nie musisz instalować żadnych bibliotek.

Uzyskiwanie tokenów dostępu OAuth 2.0

Poniższe kroki pokazują, jak aplikacja wchodzi w interakcję z serwerem OAuth 2.0 Google, aby uzyskać zgodę użytkownika na wykonanie żądania interfejsu API w jego imieniu. Zanim aplikacja będzie mogła wykonać żądanie interfejsu API Google, które wymaga autoryzacji użytkownika, musi uzyskać jego zgodę.

Poniższa lista zawiera podsumowanie tych kroków:

  1. Aplikacja określa, jakich uprawnień potrzebuje.
  2. Aplikacja przekierowuje użytkownika do Google wraz z listą wymaganych uprawnień.
  3. Użytkownik decyduje, czy przyznać aplikacji uprawnienia.
  4. Aplikacja sprawdza, jaką decyzję podjął użytkownik.
  5. 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 żądania autoryzacji. To żądanie określa parametry, które identyfikują Twoją aplikację i definiują uprawnienia, o które użytkownik zostanie poproszony w celu przyznania ich Twojej aplikacji.

  • Jeśli do uwierzytelniania i autoryzacji OAuth 2.0 używasz biblioteki klienta Google, tworzysz i konfigurujesz 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 w przypadku aplikacji serwera internetowego. Przykłady w poszczególnych językach pokazują też, jak używać biblioteki klienta lub biblioteki autoryzacji do skonfigurowania 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, aby zidentyfikować Twoją aplikację. (Więcej informacji o tym pliku znajdziesz w sekcji Tworzenie danych uwierzytelniających). Obiekt określa też zakresy, do których Twoja 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_typeinclude_granted_scopes.

Na przykład ten kod wysyła żądanie dostępu tylko do odczytu w trybie 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 korzysta z modułu google-auth-oauthlib.flow do utworzenia żądania autoryzacji.

Kod tworzy obiekt Flow, który identyfikuje Twoją aplikację za pomocą informacji z pliku client_secret.json pobranego po utworzeniu danych logowania. Obiekt ten określa też zakresy, do których Twoja aplikacja żąda dostępu, 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_typeinclude_granted_scopes.

Na przykład ten kod wysyła żądanie dostępu tylko do odczytu w trybie 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 Twoja aplikacja potrzebuje dostępu, oraz adres URL punktu końcowego autoryzacji aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0.

Na przykład ten kod wysyła żądanie dostępu tylko do odczytu w trybie 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 identyfikowania 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: wartość refresh_token jest zwracana tylko podczas 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 internetowego:

Parametry
client_id Wymagany

Identyfikator klienta Twojej aplikacji. Tę wartość znajdziesz w  .

redirect_uri Wymagany

Określa, dokąd serwer API przekierowuje użytkownika po zakończeniu procesu autoryzacji. Wartość musi być dokładnie taka sama jak jeden z autoryzowanych identyfikatorów URI przekierowania dla klienta OAuth 2.0, który został skonfigurowany w  . Jeśli ta wartość nie pasuje do autoryzowanego identyfikatora URI przekierowania dla podanego parametru client_id, pojawi się błąd redirect_uri_mismatch.

Pamiętaj, że schemat http lub https, wielkość liter i ukośnik na końcu („/”) muszą być identyczne.

response_type Wymagany

Określa, czy punkt końcowy Google OAuth 2.0 zwraca kod autoryzacji.

W przypadku aplikacji serwera internetowego ustaw wartość parametru na code.

scope Wymagany

Lista zakresów oddzielonych spacjami, które identyfikują zasoby, do których aplikacja może uzyskać dostęp w imieniu użytkownika. Te wartości informują ekran zgody, który Google wyświetla użytkownikowi.

Zakresy umożliwiają aplikacji żądanie dostępu tylko do potrzebnych zasobów, a użytkownikom – kontrolowanie zakresu dostępu przyznawanego aplikacji. Dlatego istnieje 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. Prosząc o dostęp do danych użytkownika w odpowiednim kontekście za pomocą uwierzytelniania stopniowego, pomagasz użytkownikom łatwiej zrozumieć, dlaczego Twoja aplikacja potrzebuje dostępu, o który prosi.

access_type Zalecane

Określa, czy aplikacja może odświeżać tokeny dostępu, gdy użytkownik nie jest obecny w przeglądarce. Prawidłowe wartości parametru to online (wartość domyślna) i offline.

Ustaw wartość offline, jeśli aplikacja musi odświeżać tokeny dostępu, gdy użytkownik nie korzysta z przeglądarki. Jest to metoda odświeżania tokenów dostępu opisana w dalszej części tego dokumentu. Ta wartość nakazuje serwerowi autoryzacji Google zwrócenie tokena odświeżania i tokena dostępu przy pierwszym użyciu przez aplikację kodu autoryzacji do wymiany na tokeny.

state Zalecane

Określa dowolną wartość ciągu znaków, której aplikacja używa do utrzymywania stanu między żądaniem autoryzacji a odpowiedzią serwera autoryzacji. Serwer zwraca dokładną wartość, którą wysyłasz jako parę name=value w komponencie zapytania URL (?) w redirect_uri po tym, jak użytkownik wyrazi zgodę na prośbę aplikacji o dostęp lub ją odrzuci.

Możesz używać tego parametru do różnych celów, np. do kierowania użytkownika do odpowiedniego zasobu w aplikacji, wysyłania wartości nonce i ograniczania ryzyka związanego z fałszowaniem żądań z innych witryn. Ponieważ wartość redirect_uri można odgadnąć, użycie wartości state może zwiększyć pewność, że przychodzące połączenie jest wynikiem żądania uwierzytelnienia. Jeśli wygenerujesz losowy ciąg znaków lub zakodujesz hash pliku cookie albo inną wartość, która rejestruje stan klienta, możesz zweryfikować odpowiedź, aby dodatkowo upewnić się, że żądanie i odpowiedź pochodzą z tej samej przeglądarki. Zapewni to ochronę przed atakami, takimi jak fałszowanie żądań między witrynami. Przykład tworzenia i potwierdzania tokena state znajdziesz w dokumentacji OpenID Connect.

include_granted_scopes Opcjonalny

Umożliwia aplikacjom korzystanie z autoryzacji stopniowej w celu zgłaszania w odpowiednim kontekście próśb o dostęp do dodatkowych zakresów. Jeśli ustawisz wartość tego parametru na true i żądanie autoryzacji zostanie zaakceptowane, nowy token dostępu będzie obejmować również wszystkie zakresy, do których użytkownik wcześniej przyznał aplikacji dostęp. Przykłady znajdziesz w sekcji Autoryzacja przyrostowa.

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ę logowania wielokrotnego.

Ustaw wartość parametru na adres e-mail lub identyfikator sub, który jest odpowiednikiem identyfikatora Google użytkownika.

prompt Opcjonalny

Lista promptów rozdzielonych spacjami, w której rozróżniana jest wielkość liter, które mają być wyświetlane użytkownikowi. Jeśli nie określisz tego parametru, użytkownik zobaczy prośbę tylko przy pierwszym żądaniu dostępu przez Twój projekt. Więcej informacji znajdziesz w artykule Ponowne proszenie użytkowników o zgodę.

Możliwe wartości to:

none Nie wyświetlaj żadnych ekranów uwierzytelniania ani zgody. Nie można jej określać z innymi wartościami.
consent Poproś użytkownika o zgodę.
select_account Poproś użytkownika o wybranie konta.

Krok 2. Przekieruj na serwer 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 następuje również wtedy, gdy aplikacja po raz pierwszy potrzebuje dostępu do dodatkowych zasobów, do których nie ma jeszcze uprawnień.

PHP

  1. Wygeneruj adres URL, aby wysłać żądanie dostępu do serwera OAuth 2.0 Google:
    $auth_url = $client->createAuthUrl();
  2. Przekieruj użytkownika na stronę $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 Flask do tworzenia aplikacji internetowych:

return flask.redirect(authorization_url)

Ruby

  1. Wygeneruj adres URL, aby wysłać żądanie dostępu do serwera OAuth 2.0 Google:
    auth_uri = authorizer.get_authorization_url(request: request)
  2. Przekieruj użytkownika na stronę auth_uri.

Node.js

  1. Użyj wygenerowanego adresu URL authorizationUrl z kroku 1, aby wysłać żądanie dostępu do serwera OAuth 2.0 Google.generateAuthUrl
  2. 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łem na wiersze i spacjami dla większej czytelności.

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//oauth2.example.com/code&
 client_id=client_id

Po utworzeniu adresu URL żądania przekieruj na niego użytkownika.

Serwer OAuth 2.0 Google uwierzytelnia użytkownika i uzyskuje jego zgodę na dostęp aplikacji do żądanych zakresów. Odpowiedź jest odsyłana do Twojej aplikacji za pomocą podanego adresu URL przekierowania.

Krok 3. Google prosi użytkownika o zgodę

Na tym etapie użytkownik decyduje, czy przyznać aplikacji żądany dostęp. Na tym etapie Google wyświetla okno zgody, w którym podaje nazwę aplikacji i usługi interfejsu API Google, do których aplikacja chce uzyskać dostęp za pomocą danych logowania użytkownika, oraz podsumowanie zakresów dostępu, które mają zostać przyznane. Użytkownik może wtedy wyrazić zgodę na przyznanie dostępu do co najmniej jednego zakresu, o który prosi aplikacja, lub odrzucić prośbę.

Na tym etapie aplikacja nie musi nic robić, ponieważ czeka na odpowiedź z serwera Google OAuth 2.0, która będzie wskazywać, czy przyznano dostęp. Odpowiedź jest wyjaśniona w kolejnym kroku.

Błędy

Żądania wysyłane do punktu końcowego autoryzacji OAuth 2.0 Google mogą wyświetlać komunikaty o błędach widoczne dla użytkownika zamiast oczekiwanych procesów uwierzytelniania i autoryzacji. Poniżej znajdziesz listę typowych kodów błędów i sugerowanych rozwiązań.

admin_policy_enforced

Konto Google nie może autoryzować co najmniej jednego z zakresów, o które prosisz, 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 wrażliwych i ograniczonych, dopóki dostęp nie zostanie wyraźnie przyznany 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 osadzonym agencie użytkownika, który jest niedozwolony zgodnie z zasadami Google dotyczącymi protokołu OAuth 2.0.

Android

Deweloperzy aplikacji na Androida mogą napotkać ten komunikat o błędzie podczas otwierania próśb o autoryzację w android.webkit.WebView. Deweloperzy powinni zamiast tego używać bibliotek Androida, takich jak Logowanie przez Google na Androidzie lub AppAuth na Androida od OpenID Foundation.

Deweloperzy stron internetowych mogą napotkać ten błąd, gdy aplikacja na Androida otworzy ogólny link do strony internetowej w osadzonym agencie użytkownika, a użytkownik przejdzie z Twojej witryny do punktu końcowego autoryzacji OAuth 2.0 w Google. Deweloperzy powinni zezwalać na otwieranie ogólnych linków w domyślnym programie obsługi linków w systemie operacyjnym, który obejmuje programy obsługi linków do aplikacji na Androida lub domyślną aplikację przeglądarki. Obsługiwana jest też biblioteka kart niestandardowych Chrome na Androida.

iOS

Deweloperzy aplikacji na iOS i macOS mogą napotkać ten błąd podczas otwierania próśb o autoryzację w WKWebView. Deweloperzy powinni zamiast tego używać bibliotek iOS, takich jak Logowanie przez Google na iOS lub AppAuth na iOS od OpenID Foundation.

Deweloperzy stron internetowych mogą napotkać ten błąd, gdy aplikacja na iOS lub macOS otworzy ogólny link internetowy w osadzonym agencie użytkownika, a użytkownik przejdzie z Twojej witryny do punktu końcowego autoryzacji OAuth 2.0 Google. Deweloperzy powinni zezwalać na otwieranie ogólnych linków w domyślnym programie obsługi linków w systemie operacyjnym, który obejmuje programy obsługi linków uniwersalnych lub 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 Konfigurowanie 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ę na uzyskanie nowych tokenów. Jeśli ten błąd nadal występuje, sprawdź, czy aplikacja jest 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

Parametr redirect_uri przekazany w żądaniu autoryzacji nie pasuje do autoryzowanego identyfikatora URI przekierowania dla identyfikatora klienta OAuth. Sprawdź autoryzowane identyfikatory URI przekierowania w sekcji .

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

W wysłanym przez Ciebie żądaniu wystąpił błąd. Może to wynikać z kilku przyczyn:

  • Żądanie nie zostało prawidłowo sformatowane
  • W prośbie brakowało wymaganych parametrów
  • Żądanie używa metody autoryzacji, której Google nie obsługuje. Sprawdź, czy Twoja 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, który jest zwracany do serwera WWW, pojawia się w ciągu zapytania, jak pokazano poniżej:

Odpowiedź o błędzie:

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 wysyła żądanie dostępu tylko do odczytu w celu wyświetlania metadanych plików na Dysku Google oraz dostępu tylko do odczytu w celu wyświetlania 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//oauth2.example.com/code&
 client_id=client_id

Po zakończeniu procesu OAuth 2.0 nastąpi przekierowanie na adres http://localhost/oauth2callback, co prawdopodobnie spowoduje błąd 404 NOT FOUND, chyba że na Twoim komputerze lokalnym jest plik pod tym adresem. W kolejnym kroku znajdziesz więcej informacji o danych zwracanych w identyfikatorze URI, gdy użytkownik zostanie przekierowany z powrotem do Twojej aplikacji.

Krok 5. Wymień kod autoryzacji na tokeny odświeżania i dostępu

Gdy serwer internetowy 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 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 the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    '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 na adres URL, który pierwotnie zażądał autoryzacji. Odroczy to wymianę kodu, tymczasowo przechowując wyniki 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 z  .
client_secret Tajny klucz klienta uzyskany z  .
code Kod autoryzacji zwrócony w odpowiedzi na pierwsze żą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 w projekcie w  dla danego client_id.

Poniższy fragment zawiera przykładowe żądanie:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

W odpowiedzi na to żądanie Google zwraca 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 w access_typepoczątkowym żądaniu wysłanym do serwera autoryzacji Google aplikacja ustawiła parametr offline.

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 do momentu, gdy użytkownik cofnie dostęp lub token odświeżania wygaśnie. To pole jest obecne w odpowiedzi tylko wtedy, gdy w początkowym żądaniu wysłanym do serwera autoryzacji Google ustawisz parametr access_type 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 czasowy.
scope Zakresy dostępu przyznane przez access_token w postaci listy ciągów znaków oddzielonych spacjami, w których rozróżniana jest wielkość liter.
token_type Typ zwracanego tokena. Obecnie wartość tego pola jest zawsze ustawiona na Bearer.

Poniższy fragment kodu pokazuje przykładową odpowiedź:

{
  "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 możesz zamiast oczekiwanej odpowiedzi napotkać ten błąd. Poniżej znajdziesz listę typowych kodów błędów i sugerowanych rozwiązań.

invalid_grant

Podany kod autoryzacji jest nieprawidłowy lub ma nieprawidłowy format. Poproś o nowy kod, ponownie uruchamiając proces OAuth, aby ponownie wyświetlić użytkownikowi prośbę o zgodę.

Krok 6. Sprawdź, które zakresy użytkownicy przyznali aplikacji

Gdy prosisz o wiele uprawnień (zakresów), użytkownicy mogą nie przyznać aplikacji dostępu do wszystkich z nich. Aplikacja musi sprawdzać, które zakresy zostały faktycznie przyznane, i prawidłowo obsługiwać sytuacje, w których niektóre uprawnienia są odrzucane. Zazwyczaj polega to na wyłączaniu funkcji, które korzystają z tych odrzuconych zakresów.

Są jednak wyjątki. Aplikacje Google Workspace Enterprise z delegowaniem uprawnień w całej domenie lub aplikacje oznaczone jako zaufane pomijają ekran zgody na szczegółowe uprawnienia. W przypadku tych aplikacji użytkownicy nie zobaczą ekranu akceptacji szczegółowych uprawnień. Zamiast tego aplikacja otrzyma wszystkie żądane zakresy lub nie otrzyma żadnego z nich.

Więcej informacji znajdziesz w artykule Jak zarządzać szczegółowymi uprawnieniami.

PHP

Aby sprawdzić, które zakresy użytkownik przyznał, 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, do których użytkownik przyznał dostęp Twojej aplikacji.

credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    '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

Gdy prosisz o kilka zakresów jednocześnie, sprawdź, które z nich zostały przyznane, korzystając z 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

Gdy prosisz o kilka zakresów jednocześnie, sprawdź, które z nich zostały przyznane, korzystając z 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ł Twojej aplikacji dostęp do określonego zakresu, sprawdź pole scope w odpowiedzi tokena dostępu. Zakresy dostępu przyznane przez token dostępu wyrażone jako lista ciągów znaków oddzielonych spacjami, w których wielkość liter ma znaczenie.

Na przykład poniższa przykładowa odpowiedź z tokenem dostępu wskazuje, że użytkownik przyznał Twojej aplikacji dostęp do uprawnień 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 wywołać interfejsy API Google za pomocą tokena dostępu, wykonaj te czynności:

  1. Jeśli musisz 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 metody setAccessToken:
    $client->setAccessToken($access_token);
  2. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzy się, przekazując do konstruktora interfejsu API, który chcesz wywołać, autoryzowany obiekt Google\Client. Aby na przykład wywołać interfejs Drive API:
    $drive = new Google\Service\Drive($client);
  3. Wysyłaj żądania do usługi 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 logowania autoryzacji 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.

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzy się, wywołując metodę googleapiclient.discovery biblioteki build z nazwą i wersją interfejsu API oraz danymi logowania użytkownika: Na przykład, aby wywołać wersję 3 interfejsu Drive API:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. Wysyłaj żądania do usługi 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().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 logowania autoryzacji 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.

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Na przykład, aby wywołać wersję 3 interfejsu Drive API:
    drive = Google::Apis::DriveV3::DriveService.new
  2. Ustaw dane logowania w usłudze:
    drive.authorization = credentials
  3. Wysyłaj żądania do usługi 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

Autoryzację można też przyznać dla poszczególnych metod, podając parametr options w metodzie:

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ń 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 poniższy 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że go używać do wywoływania interfejsu API Google w imieniu danego konta użytkownika, jeśli zakresy dostępu wymagane przez interfejs API zostały przyznane. Aby to zrobić, dołącz token dostępu do żądania wysyłanego do interfejsu API, uwzględniając parametr zapytania access_token lub wartość nagłówka HTTP AuthorizationBearer. W miarę możliwości preferowany jest nagłówek 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 (np. podczas wywoływania interfejsu Drive Files API).

Wszystkie interfejsy API Google i ich zakresy możesz wypróbować na stronie OAuth 2.0 Playground.

Przykłady żądań 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 za pomocą 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, w którym użyto opcji nagłówka HTTP (preferowanej):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Możesz też wybrać opcję parametru ciągu zapytania:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Pełny przykład

W przykładzie poniżej po uwierzytelnieniu użytkownika i wyrażeniu przez niego zgody na dostęp aplikacji do metadanych Dysku użytkownika zostanie wydrukowana lista plików na Dysku Google użytkownika w formacie JSON.

PHP

Aby uruchomić ten przykład:

  1. W sekcji API Consoledodaj adres URL komputera lokalnego do listy adresów URL przekierowania. Na przykład dodaj http://localhost:8080.
  2. Utwórz nowy katalog i przejdź do niego. Na przykład:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. Zainstaluj bibliotekę klienta interfejsu API Google dla języka PHP za pomocą Composer:
    composer require google/apiclient:^2.15.0
  4. Utwórz pliki index.phpoauth2callback.php z tą treścią:
  5. Uruchom przykład na wbudowanym serwerze WWW PHP:
    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 testowanie przepływu OAuth 2.0. Jeśli przejdziesz do tego adresu URL, zobaczysz 5 linków:

  • Wywołaj interfejs Drive API: ten link prowadzi do strony, która próbuje wykonać przykładowe żądanie interfejsu API, jeśli użytkownicy przyznali uprawnienia. W razie potrzeby rozpoczyna proces autoryzacji. Jeśli operacja się uda, na stronie pojawi się odpowiedź interfejsu API.
  • Strona testowa do wywoływania interfejsu Calendar API: ten link prowadzi do strony testowej, która próbuje wykonać przykładowe żądanie interfejsu Calendar API, jeśli użytkownicy przyznali uprawnienia. W razie potrzeby rozpoczyna proces autoryzacji. Jeśli operacja się uda, na stronie pojawi się odpowiedź interfejsu API.
  • Bezpośrednie testowanie procesu uwierzytelniania: ten link prowadzi do strony, która próbuje przeprowadzić użytkownika przez proces autoryzacji. Aplikacja prosi o uprawnienia do przesyłania autoryzowanych żądań interfejsu API w imieniu użytkownika.
  • Odwołaj bieżące dane logowania: ten link prowadzi do strony, na której odwoływane są uprawnienia, które użytkownik przyznał już aplikacji.
  • Wyczyść dane logowania sesji Flask: ten link usuwa dane logowania autoryzacji, które są przechowywane w sesji Flask. Dzięki temu możesz sprawdzić, co się stanie, gdy użytkownik, który przyznał już Twojej aplikacji uprawnienia, spróbuje wykonać żądanie interfejsu API w nowej sesji. Umożliwia też sprawdzenie odpowiedzi interfejsu API, którą otrzymałaby Twoja aplikacja, gdyby użytkownik cofnął uprawnienia przyznane Twojej aplikacji, a ona nadal próbowała autoryzować żądanie za pomocą cofniętego tokena dostępu.
# -*- coding: utf-8 -*-

import os
import flask
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 credentials from the session.
    credentials = google.oauth2.credentials.Credentials(
        **flask.session['credentials'])

    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.
    # ACTION ITEM: In a production app, you likely want to save these
    #              credentials in a persistent database instead.
    flask.session['credentials'] = credentials_to_dict(credentials)

    return flask.jsonify(**files)
  else:
    # User didn't authorize read-only Drive activity permission.
    # Update UX and application accordingly
    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.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  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:
    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,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          '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="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<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="/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="/test">test the ' +
          '    API request</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żyto 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:

  1. W sekcji API Consoledodaj adres URL komputera lokalnego do listy adresów URL przekierowania. Na przykład dodaj http://localhost.
  2. Upewnij się, że masz zainstalowaną wersję Node.js z utrzymaniem LTS, aktywną LTS lub bieżącą.
  3. Utwórz nowy katalog i przejdź do niego. Na przykład:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. Zainstaluj Google API Client Library dla Node.js za pomocą npm:
    npm install googleapis
  5. Utwórz pliki main.js z tą treścią.
  6. 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 języku Python wykorzystuje platformę Flask i bibliotekę Requests, aby zademonstrować proces internetowy OAuth 2.0. W tym procesie zalecamy używanie 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

Aby pomóc deweloperom w zapewnieniu bezpieczeństwa aplikacji, Google stosuje do identyfikatorów URI przekierowania te reguły weryfikacji: Identyfikatory URI przekierowania muszą być zgodne z tymi regułami. Definicje terminów domena, host, ścieżka, zapytanie, schemat i informacje o użytkowniku znajdziesz w sekcji 3 dokumentu RFC 3986.

Reguły weryfikacji
Schemat

Identyfikatory URI przekierowania muszą używać schematu HTTPS, a nie zwykłego protokołu HTTP. Identyfikatory URI hosta lokalnego (w tym identyfikatory URI adresu IP hosta lokalnego) są zwolnione z tej reguły.

Osoba prowadząca

Hosty nie mogą być surowymi adresami IP. Adresy IP hosta lokalnego są wyłączone z tej reguły.

Domena
  • Domeny najwyższego poziomu hosta (domeny najwyższego poziomu) muszą należeć do listy sufiksów publicznych.
  • Domeny hosta nie mogą być “googleusercontent.com”.
  • Identyfikatory URI przekierowania nie mogą zawierać domen skracających adresy URL (np. goo.gl), chyba że aplikacja jest właścicielem domeny. Jeśli aplikacja, która jest właścicielem domeny skracającej, zdecyduje się na przekierowanie do tej domeny, identyfikator URI przekierowania musi zawierać “/google-callback/” w ścieżce lub kończyć się znakiem “/google-callback”.
  • Userinfo

    Identyfikatory URI przekierowania nie mogą zawierać podkomponentu userinfo.

    Ścieżka

    Identyfikatory URI przekierowania nie mogą zawierać przemierzania ścieżki (zwanego też cofaniem się w katalogach), które jest reprezentowane przez znaki “/..” lub “\..” albo ich kodowanie URL.

    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, w tym:
    • Symbole wieloznaczne ('*')
    • Znaki ASCII, których nie można wydrukować
    • Nieprawidłowe kodowanie z użyciem znaków procentów (każde kodowanie z użyciem znaków procentów, które nie jest zgodne z formatem kodowania URL, czyli znaku procentu, po którym następują 2 cyfry szesnastkowe)
    • znaki puste (zakodowany znak NULL, np. %00, %C0%80)

    Autoryzacja przyrostowa

    W protokole OAuth 2.0 aplikacja prosi o autoryzację dostępu do zasobów, które są identyfikowane przez zakresy. Sprawdzoną metodą zapewniającą komfort użytkownikom jest proszenie o autoryzację dostępu do zasobów w momencie, gdy są one potrzebne. Aby to umożliwić, serwer autoryzacji Google obsługuje autoryzację przyrostową. Ta funkcja umożliwia wysyłanie żądań zakresów w miarę potrzeb. Jeśli użytkownik przyzna uprawnienia do nowego zakresu, zwracany jest kod autoryzacji, który można wymienić na token zawierający wszystkie zakresy, do których użytkownik przyznał uprawnienia w projekcie.

    Na przykład aplikacja, która umożliwia użytkownikom odsłuchiwanie utworów muzycznych i tworzenie miksów, może potrzebować bardzo niewielu zasobów podczas logowania – być może tylko nazwy osoby logującej się. Zapisanie ukończonego miksu będzie jednak wymagało dostępu do Dysku Google. Większość użytkowników uznałaby za naturalne, gdyby prośba o dostęp do Dysku Google pojawiała się tylko wtedy, gdy aplikacja faktycznie go potrzebuje.

    W tym przypadku podczas logowania aplikacja może poprosić o zakresy openidprofile, aby przeprowadzić podstawowe logowanie, a później, podczas pierwszego żądania zapisu miksu, poprosić 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 z zakresów włączonych do nowego, połączonego upoważnienia.
    • Gdy używasz tokena odświeżania do uzyskania tokena dostępu w przypadku autoryzacji łączonej, token dostępu reprezentuje autoryzację łączoną i może być używany w przypadku dowolnej z wartości scope zawartych w odpowiedzi.
    • Łączna autoryzacja obejmuje wszystkie zakresy, które użytkownik przyznał projektowi interfejsu API, nawet jeśli przyznanie zostało zainicjowane 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 inny zakres tej samej aplikacji za pomocą klienta mobilnego, połączone uprawnienia będą obejmować oba zakresy.
    • Jeśli cofniesz token reprezentujący połączoną autoryzację, dostęp do wszystkich zakresów autoryzacji w imieniu powiązanego użytkownika zostanie cofnięty jednocześnie.

    Przykłady kodu w różnych językach w kroku 1. Ustaw parametry autoryzacji i przykładowy adres URL przekierowania HTTP/REST w kroku 2. Przekieruj na serwer OAuth 2.0 Google korzystają z autoryzacji przyrostowej. Przykłady kodu poniżej pokazują też kod, który musisz 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 zawiera wcześniej przyznane zakresy. Jest bardzo prawdopodobne, że include_granted_scopes nie będzie jedynym argumentem słowa kluczowego, który ustawisz, jak pokazano w poniższym przykładzie.

    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//oauth2.example.com/code&
      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 uwierzytelniającymi dla powiązanego żądania API. Token dostępu możesz odświeżyć bez proszenia użytkownika o uprawnienia (nawet gdy użytkownik jest nieobecny), 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_type na wartość offline podczas 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.

    Prośba o dostęp offline jest wymagana w przypadku każdej aplikacji, która potrzebuje dostępu do interfejsu API Google, gdy użytkownik nie jest obecny. Na przykład aplikacja, która wykonuje usługi tworzenia kopii zapasowych lub działania w określonych godzinach, musi mieć możliwość odświeżania tokena dostępu, gdy użytkownik jest nieobecny. Domyślny styl dostępu to online.

    Podczas procesu autoryzacji aplikacje internetowe po stronie serwera, zainstalowane aplikacje i urządzenia uzyskują tokeny odświeżania. 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 interfejsu 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 do uzyskiwania dostępu do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta w razie potrzeby odświeży token dostępu.

    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 zezwolenie. Jest bardzo prawdopodobne, że access_type nie będzie jedynym argumentem słowa kluczowego, który ustawisz, 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')

    Gdy użytkownik przyzna dostęp offline do żądanych zakresów, możesz nadal używać klienta interfejsu API do uzyskiwania dostępu do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta w razie potrzeby odświeży token dostępu.

    Ruby

    Jeśli aplikacja potrzebuje dostępu offline do interfejsu API Google, ustaw typ dostępu klienta interfejsu 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 do uzyskiwania dostępu do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta w razie potrzeby odświeży token dostępu.

    Node.js

    Jeśli aplikacja potrzebuje dostępu offline do interfejsu API Google, ustaw typ dostępu klienta interfejsu 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 do uzyskiwania dostępu do interfejsów API Google w imieniu użytkownika, gdy jest on offline. Obiekt klienta w razie potrzeby odświeży token dostępu.

    Tokeny dostępu wygasają. Ta biblioteka automatycznie użyje tokena odświeżania, aby uzyskać nowy token dostępu, jeśli ten ma wygasnąć. Łatwym sposobem na zapewnienie, ż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 Twoja aplikacja ma już wymagane uprawnienia, ale nie ma odpowiednich ograniczeń dotyczących otrzymywania tokena odświeżania, musisz ponownie autoryzować aplikację, aby otrzymać nowy token odświeżania.

    Aby ustawić refresh_token w późniejszym czasie, możesz użyć metody setCredentials:

    oauth2Client.setCredentials({
      refresh_token: `STORED_REFRESH_TOKEN`
    });

    Gdy klient ma token odświeżania, tokeny dostępu będą uzyskiwane i odświeżane automatycznie podczas następnego wywołania interfejsu API.

    HTTP/REST

    Aby odświeżyć token dostępu, aplikacja wysyła żądanie HTTPS POST do serwera autoryzacji Google (https://oauth2.googleapis.com/token), które zawiera te parametry:

    Pola
    client_id Identyfikator klienta uzyskany z  API Console.
    client_secret Klucz klienta uzyskany z  API Console.
    grant_type Zgodnie ze specyfikacją OAuth 2.0 wartość tego pola musi być ustawiona na refresh_token.
    refresh_token Token odświeżania zwrócony z wymiany kodu autoryzacji.

    Poniższy fragment zawiera przykładowe żądanie:

    POST /token HTTP/1.1
    Host: oauth2.googleapis.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=your_client_id&
    client_secret=your_client_secret&
    refresh_token=refresh_token&
    grant_type=refresh_token

    Dopóki użytkownik nie cofnie dostępu przyznanego aplikacji, serwer tokenów zwraca obiekt JSON zawierający nowy token dostępu. Poniższy fragment kodu pokazuje przykładową odpowiedź:

    {
      "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. Obowiązuje limit na kombinację klient/użytkownik i limit na użytkownika we wszystkich klientach. Tokeny odświeżania należy zapisywać w pamięci długoterminowej i używać ich tak długo, jak są ważne. Jeśli aplikacja zażą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żnianie tokena

    W niektórych przypadkach użytkownik może chcieć cofnąć dostęp przyznany aplikacji. Użytkownik może cofnąć dostęp, otwierając Ustawienia konta. Więcej informacji znajdziesz w sekcji Usuwanie dostępu witryny lub aplikacji w artykule pomocy Strony internetowe i aplikacje innych firm z dostępem do Twojego konta.

    Aplikacja może też programowo unieważnić przyznany jej dostęp. Programowe wycofywanie jest ważne w przypadkach, gdy użytkownik rezygnuje z subskrypcji, usuwa aplikację lub zasoby interfejsu API wymagane przez aplikację uległy znacznym zmianom. Innymi słowy, część procesu usuwania może obejmować żądanie interfejsu API, aby upewnić się, że uprawnienia przyznane wcześniej aplikacji zostały usunięte.

    PHP

    Aby programowo unieważnić token, 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)

    Może to być token dostępu lub token odświeżania. Jeśli token jest tokenem dostępu i ma odpowiedni token odświeżania, token odświeżania również zostanie unieważniony.

    Jeśli wycofanie zostanie przetworzone, kod stanu odpowiedzi to 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 token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiedni token odświeżania, token odświeżania również zostanie unieważniony.

    Jeśli wycofanie zostanie przetworzone, kod stanu odpowiedzi to 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}

    Może to być token dostępu lub token odświeżania. Jeśli token jest tokenem dostępu i ma odpowiedni token odświeżania, token odświeżania również zostanie unieważniony.

    Jeśli wycofanie 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 uzyskiwania zgody. Użytkownicy mogą przyznać dostęp 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 czasowy, token odświeżania wygaśnie po upływie określonego czasu. Pamiętaj, że tokeny odświeżania mogą zostać unieważnione wcześniej w określonych okolicznościach. Szczegółowe informacje znajdziesz w tych przypadkach. Pole refresh_token_expires_in zwrócone w odpowiedzi wymiany kodu autoryzacji wskazuje w takich przypadkach czas pozostały do wygaśnięcia tokena odświeżania.

    Wdrażanie Ochrony wszystkich kont

    Dodatkowym krokiem, który należy podjąć w celu ochrony kont użytkowników, jest wdrożenie ochrony międzykontowej za pomocą usługi ochrony międzykontowej 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. Na podstawie tych informacji możesz podejmować działania w zależności od tego, jak chcesz reagować na zdarzenia.

    Oto kilka przykładów typów zdarzeń wysyłanych do Twojej aplikacji przez usługę ochrony 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 wdrażaniu ochrony wszystkich kont i pełną listę dostępnych zdarzeń znajdziesz na stronie Ochrona kont użytkowników za pomocą ochrony wszystkich kont .