Korzystanie z protokołu OAuth 2.0 w aplikacjach serwerowych

Ten dokument wyjaśnia, jak aplikacje serwera internetowego korzystają z bibliotek klienta interfejsu API Google lub punktów końcowych OAuth 2.0 Google, aby zaimplementować autoryzację OAuth 2.0 w celu uzyskania dostępu do interfejsu YouTube Data API.

OAuth 2.0 umożliwia użytkownikom udostępnianie określonych danych aplikacji przy jednoczesnym zachowaniu poufności nazw, haseł i innych informacji. Aplikacja może na przykład używać OAuth 2.0, aby uzyskać uprawnienia do przesyłania filmów na kanał użytkownika w YouTube.

Ten proces OAuth 2.0 jest przeznaczony do autoryzacji użytkownika. Jest przeznaczony do aplikacji, które mogą przechowywać poufne informacje i utrzymywać stan. Prawidłowo autoryzowana aplikacja serwera WWW może uzyskać dostęp do interfejsu API, gdy użytkownik wchodzi w interakcję z aplikacją lub gdy ją opuszcza.

Aplikacje serwera WWW często używają też kont usług do autoryzowania żądań interfejsu API, zwłaszcza gdy wywołują interfejsy Cloud API, aby uzyskać dostęp do danych opartych na projekcie, a nie danych dotyczących konkretnego użytkownika. Aplikacje serwera WWW mogą używać kont usługi w połączeniu z autoryzacją użytkownika. Pamiętaj, że interfejs YouTube Data API obsługuje przepływ danych na koncie usługi tylko w przypadku właścicieli treści w YouTube, którzy są właścicielami wielu kanałów w YouTube i nimi zarządzają. W szczególności właściciele treści mogą używać kont usługi do wywoływania metod interfejsu API, które obsługują parametr onBehalfOfContentOwner żądania.

Biblioteki klienta

Przykłady dotyczące poszczególnych języków na tej stronie używają bibliotek klienta interfejsu API Google do implementowania autoryzacji OAuth 2.0. Aby uruchomić przykłady kodu, musisz najpierw zainstalować bibliotekę klienta dla wybranego języka.

Gdy używasz biblioteki klienta interfejsu API Google do obsługi procesu OAuth 2.0 w aplikacji, biblioteka klienta wykonuje wiele działań, które aplikacja musiałaby wykonać samodzielnie. Na przykład określa, kiedy aplikacja może używać lub odświeżać zapisane tokeny dostępu, a także kiedy musi ponownie uzyskać zgodę. Biblioteka klienta generuje też prawidłowe adresy URL przekierowania i pomaga implementować moduły przekierowania, które zamieniają kody autoryzacji na tokeny dostępu.

Biblioteki klienta interfejsu API Google przeznaczone do aplikacji serwerowych 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. Na stronie Biblioteka znajdź i włącz interfejs YouTube Data API. Znajdź inne interfejsy API, z których będzie korzystać Twoja aplikacja, i te też włącz.

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ć poświadczenia autoryzacyjne, które identyfikują ją na serwerze OAuth 2.0 Google. Z tych instrukcji dowiesz się, jak utworzyć poświadczenia tożsamości do projektu. Twoje aplikacje mogą wtedy używać tych danych logowania do uzyskiwania dostępu do interfejsów API, które zostały włączone w tym projekcie.

  1. Go to the Credentials page.
  2. Kliknij Utwórz dane logowania > Identyfikator klienta OAuth.
  3. Wybierz typ aplikacji Aplikacja internetowa.
  4. Wypełnij formularz i kliknij Utwórz. Aplikacje korzystające z języków i frameworków takich jak PHP, Java, Python, Ruby i .NET muszą określać autoryzowane identyfikatory URI przekierowania. URI przekierowania to punkty końcowe, do których serwer OAuth 2.0 może wysyłać odpowiedzi. Te punkty końcowe muszą być zgodne z regułami walidacji Google.

    Na potrzeby testowania możesz podać identyfikatory URI odwołujące się do lokalnego komputera, np. http://localhost:8080. Pamiętaj, że wszystkie przykłady w tym dokumencie używają jako identyfikatora URI przekierowania wartości http://localhost:8080.

    Zalecamy zaprojektowanie punktów końcowych autoryzacji aplikacji tak, aby aplikacja nie ujawniała kodów autoryzacji innym zasobom na stronie.

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

Określanie zakresów dostępu

Zakresy umożliwiają aplikacji żądanie dostępu tylko do zasobów, których potrzebuje, a także kontrolowanie przez użytkowników zakresu dostępu przyznawanego aplikacji. Dlatego może istnieć odwrotna zależność między liczbą żądanych zakresów uprawnień a prawdopodobieństwom uzyskania zgody użytkownika.

Zanim zaczniesz wdrażać autoryzację OAuth 2.0, zalecamy określenie zakresów, do których aplikacja będzie potrzebować uprawnień dostępu.

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

Interfejs YouTube Data API v3 korzysta z tych zakresów:

Zakresy
https://www.googleapis.com/auth/youtubeZarządzanie kontem YouTube
https://www.googleapis.com/auth/youtube.channel-memberships.creatorWyświetlanie listy aktualnie aktywnych użytkowników wspierających kanał, ich obecnych poziomów i dat rozpoczęcia wsparcia
https://www.googleapis.com/auth/youtube.force-sslPrzeglądanie, edytowanie i trwałe usuwanie Twoich filmów, ocen, komentarzy i napisów z YouTube
https://www.googleapis.com/auth/youtube.readonlyWyświetlanie konta YouTube
https://www.googleapis.com/auth/youtube.uploadZarządzanie filmami w YouTube
https://www.googleapis.com/auth/youtubepartnerPrzeglądaj zasoby oraz powiązane treści i zarządzaj nimi w serwisie YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditPrzeglądanie prywatnych danych kanału YouTube istotnych podczas rozmowy z partnerem YouTube

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 fragmentów kodu w tym dokumencie, musisz mieć konto Google, dostęp do internetu i przeglądarkę internetową. Jeśli używasz jednej z bibliotek klienta interfejsu API, zapoznaj się też z poniżej wymienionymi wymaganiami dotyczącymi poszczególnych języków.

PHP

Aby uruchomić przykłady kodu PHP w tym dokumencie, musisz mieć:

  • PHP w wersji 8.0 lub nowszej z zainstalowanym interfejsem wiersza poleceń (CLI) i rozszerzeniem JSON.
  • Narzędzie do zarządzania zależnościami Composer.
  • Biblioteka klienta interfejsów Google API dla języka PHP:

    composer require google/apiclient:^2.15.0

Więcej informacji znajdziesz w bibliotece klienta interfejsów API Google dla PHP.

Python

Aby uruchomić przykładowy kod Pythona w tym dokumencie, musisz mieć:

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

Jeśli nie możesz uaktualnić Pythona i powiązanego z nim przewodnika migracyjnego, zapoznaj się z notatkami do wersji biblioteki klienta interfejsu API Google dla języka Python.

Ruby

Aby uruchomić przykłady kodu Ruby w tym dokumencie, musisz mieć:

  • Ruby w wersji 2.6 lub nowszej
  • Biblioteka Google Auth Library do Ruby:

    gem install googleauth
  • Platforma do tworzenia aplikacji internetowych w Ruby o nazwie Sinatra.

    gem install sinatra

Node.js

Aby uruchomić przykładowy kod Node.js w tym dokumencie, musisz mieć:

  • Wersja LTS w ramach konserwacji, aktywna wersja LTS lub aktualna wersja Node.js.
  • Klient Node.js interfejsów API Google:

    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.

Pobieranie tokenów dostępu OAuth 2.0

Te czynności pokazują, jak aplikacja wchodzi w interakcję z serwerem OAuth 2.0 Google, aby uzyskać zgodę użytkownika na wykonanie żądania interfejsu API w imieniu tego użytkownika. Aplikacja musi mieć tę zgodę, zanim będzie mogła wykonać żądanie interfejsu Google API, które wymaga autoryzacji użytkownika.

Poniżej znajdziesz listę podsumowującą te czynności:

  1. Aplikacja określa, których uprawnień potrzebuje.
  2. Aplikacja przekierowuje użytkownika do Google wraz z listą żądanych 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ń interfejsu API w imieniu użytkownika.

Krok 1. Ustaw parametry autoryzacji

Pierwszym krokiem jest utworzenie żądania autoryzacji. Żądanie to zawiera parametry, które identyfikują Twoją aplikację i określają uprawnienia, o które użytkownik będzie proszony.

  • Jeśli do uwierzytelniania i autoryzacji OAuth 2.0 używasz biblioteki klienta Google, musisz utworzyć i skonfigurować obiekt definiujący te parametry.
  • Jeśli wywołasz punkt końcowy OAuth 2.0 Google bezpośrednio, wygenerujesz adres URL i ustawisz parametry tego adresu.

Na kartach poniżej znajdziesz listę obsługiwanych parametrów autoryzacji dla aplikacji serwera WWW. Przykłady w konkretnych językach pokazują też, jak za pomocą biblioteki klienta lub biblioteki autoryzacyjnej skonfigurować obiekt, który ustawia te parametry.

PHP

Poniższy fragment kodu tworzy obiekt Google\Client(), który definiuje parametry w żądaniu autoryzacji.

Obiekt ten używa informacji z pliku client_secret.json do identyfikowania Twojej aplikacji. (więcej informacji o tym pliku znajdziesz w sekcji Tworzenie danych uwierzytelniających). Obiekt identyfikuje też zakresy, do których aplikacja prosi o dostęp, oraz adres URL punktu końcowego autoryzacji aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0 Google. Na koniec kod ustawia opcjonalne parametry access_typeinclude_granted_scopes.

Ten kod prosi o dostęp offline do zarządzania kontem YouTube 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_YOUTUBE::YOUTUBE_FORCE_SSL);

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

Fragment kodu poniżej używa modułu google-auth-oauthlib.flow do tworzenia żądania autoryzacji.

Kod tworzy obiekt Flow, który identyfikuje Twoją aplikację za pomocą informacji z pliku client_secret.json pobranego po utworzeniu danych logowania autoryzujących. Obiekt ten identyfikuje zakresy, do których aplikacja prosi o dostęp, oraz adres URL punktu końcowego autoryzacji aplikacji, który będzie obsługiwał odpowiedź z serwera OAuth 2.0 Google. Na koniec kod ustawia opcjonalne parametry access_typeinclude_granted_scopes.

Ten kod prosi o dostęp offline do zarządzania kontem YouTube 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/youtube.force-ssl'])

# Required, indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Recommended, enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Optional, enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true',
    # Optional, if your application knows which user is trying to authenticate, it can use this
    # parameter to provide a hint to the Google Authentication Server.
    login_hint='hint@example.com',
    # Optional, set prompt to 'consent' will prompt the user for consent
    prompt='consent')

Ruby

Użyj utworzonego pliku client_secrets.json, aby skonfigurować obiekt klienta w aplikacji. Podczas konfigurowania obiektu klienta określasz zakresy, do których aplikacja musi mieć dostęp, oraz adres URL punktu końcowego autoryzacji aplikacji, który będzie obsługiwać odpowiedź z serwera OAuth 2.0.

Ten kod prosi o dostęp offline do zarządzania kontem YouTube użytkownika:

require 'googleauth'
require 'googleauth/web_user_authorizer'
require 'googleauth/stores/redis_token_store'

require 'google/apis/youtube_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 
scope = 'https://www.googleapis.com/auth/youtube.force-ssl'

# 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)

Twoja 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.

Obiekt ten 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 zgody:

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 YouTube API
const scopes = [
  'https://www.googleapis.com/auth/youtube.force-ssl'
];

// 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 przy pierwszej autoryzacji. Więcej informacji znajdziesz tutaj.

HTTP/REST

Punkt końcowy OAuth 2.0 Google znajduje się pod adresem https://accounts.google.com/o/oauth2/v2/auth. Ten punkt końcowy jest dostępny tylko przez HTTPS. Połączenia HTTP nie są akceptowane.

Serwer autoryzacji Google obsługuje te parametry ciągu zapytania w przypadku aplikacji serwera WWW:

Parametry
client_id Wymagany

Identyfikator klienta Twojej aplikacji. Znajdziesz ją w sekcji API Console: Credentials page.

redirect_uri Wymagany

Określa, dokąd serwer API przekieruje użytkownika po zakończeniu przez niego procesu autoryzacji. Wartość musi dokładnie pasować do jednego z autoryzowanych identyfikatorów URI przekierowania dla klienta OAuth 2.0 skonfigurowanego w API Console Credentials page. Jeśli ta wartość nie pasuje do autoryzowanego identyfikatora URI przekierowania dla podanego identyfikatora client_id, pojawi się błąd redirect_uri_mismatch.

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

response_type Wymagany

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

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

scope Wymagany

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

Zakresy umożliwiają aplikacji żądanie dostępu tylko do zasobów, których potrzebuje, a także kontrolowanie przez użytkowników zakresu dostępu przyznawanego aplikacji. W związku z tym istnieje odwrotna zależność między liczbą żądanych zakresów uprawnień a prawdopodobieństwom uzyskania zgody użytkownika.

Interfejs YouTube Data API v3 korzysta z tych zakresów:

Zakresy
https://www.googleapis.com/auth/youtubeZarządzanie kontem YouTube
https://www.googleapis.com/auth/youtube.channel-memberships.creatorWyświetlanie listy aktualnie aktywnych użytkowników wspierających kanał, ich obecnych poziomów i dat rozpoczęcia wsparcia
https://www.googleapis.com/auth/youtube.force-sslPrzeglądanie, edytowanie i trwałe usuwanie Twoich filmów, ocen, komentarzy i napisów z YouTube
https://www.googleapis.com/auth/youtube.readonlyWyświetlanie konta YouTube
https://www.googleapis.com/auth/youtube.uploadZarządzanie filmami w YouTube
https://www.googleapis.com/auth/youtubepartnerPrzeglądaj zasoby oraz powiązane treści i zarządzaj nimi w serwisie YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditPrzeglądanie prywatnych danych kanału YouTube istotnych podczas rozmowy z partnerem YouTube

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.

Zalecamy, aby aplikacja zawsze, gdy to możliwe, prosiła o dostęp do zakresów autoryzacji w kontekście. Wyświetlając prośby o dostęp do danych użytkownika w odpowiednim kontekście (stosując uwierzytelnianie stopniowe), pomagasz użytkownikom łatwiej zrozumieć, dlaczego Twoja aplikacja potrzebuje dostępu, o który prosi.

access_type Zalecane

Wskazuje, 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.

Jeśli aplikacja musi odświeżać tokeny dostępu, gdy użytkownik nie jest obecny w przeglądarce, ustaw tę wartość na offline. Ta metoda odświeżania tokenów dostępu jest opisana w dalszej części tego dokumentu. Ta wartość instruuje serwer autoryzacji Google, aby zwrócił token odświeżania i token dostępu za pierwszym razem, gdy aplikacja wymieni kod autoryzacji na tokeny.

state Zalecane

Określa dowolną wartość ciągu znaków, której aplikacja używa do zachowania 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 adresu URL (?) w redirect_uri, gdy użytkownik wyrazi zgodę na żądanie dostępu aplikacji lub odrzuci je.

Parametru tego można używać do różnych celów, np. do kierowania użytkownika do odpowiedniego zasobu w aplikacji, wysyłania identyfikatorów jednorazowych i ograniczania fałszowania żądań między witrynami. Ponieważ wartość redirect_uri można odgadnąć, użycie wartości state może zwiększyć pewność, że połączenie przychodzące jest wynikiem żądania uwierzytelnienia. Jeśli wygenerujesz losowy ciąg znaków lub zakodujesz hasz pliku cookie lub inną wartość, która odzwierciedla stan klienta, możesz dodatkowo sprawdzić odpowiedź, aby upewnić się, że żądanie i odpowiedź pochodzą z tego samego przeglądarki. Zapewnia to ochronę przed atakami takimi jak fałszowanie żądań między witrynami. Przykład utworzenia i potwierdzenia tokena state znajdziesz w dokumentacji OpenID Connect.

include_granted_scopes Opcjonalny

Umożliwia aplikacjom korzystanie z uwierzytelniania stopniowego do żądania dostępu do dodatkowych zakresów w kontekście. Jeśli wartość tego parametru zostanie ustawiona na true, a prośba o autoryzację zostanie zaakceptowana, 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 cząstkowa.

login_hint Opcjonalny

Jeśli aplikacja wie, który użytkownik próbuje się uwierzytelnić, może użyć tego parametru, aby przekazać wskazówkę serwerowi uwierzytelniania Google. Serwer używa tego podpowiedzi do uproszczenia procesu logowania, wypełniając wstępnie pole adresu e-mail w formularzu logowania lub wybierając odpowiednią sesję logowania wielokrotnego.

Ustaw wartość parametru jako adres e-mail lub identyfikator sub, który jest równoważny z identyfikatorem Google użytkownika.

prompt Opcjonalny

Posortowana alfabetycznie lista promptów oddzielonych spacjami, w których wielkość liter ma znaczenie. 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 Prośba o ponowne wyrażenie zgody.

Możliwe wartości to:

none Nie wyświetlaj żadnych ekranów uwierzytelniania ani ekranów zgody. Nie można go określać w połączeniu z innymi wartościami.
consent poprosić 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 zainicjować proces uwierzytelniania i autoryzacji. Zwykle dzieje się tak, gdy aplikacja musi po raz pierwszy uzyskać dostęp do danych użytkownika. W przypadku autoryzacji stopniowej ten krok wystę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 poprosić o dostęp do serwera Google OAuth 2.0:
    $auth_url = $client->createAuthUrl();
  2. Przekieruj użytkownika do $auth_url:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

Ten przykład pokazuje, jak przekierować użytkownika do adresu URL autoryzacji za pomocą platformy Flask do tworzenia aplikacji internetowych:

return flask.redirect(authorization_url)

Ruby

  1. Wygeneruj adres URL, aby poprosić o dostęp do serwera Google OAuth 2.0:
    auth_uri = authorizer.get_authorization_url(request: request)
  2. Przekieruj użytkownika na stronę auth_uri.

Node.js

  1. Aby poprosić o dostęp do serwera OAuth 2.0 Google, użyj wygenerowanego adresu URL authorizationUrletapu 1.generateAuthUrl
  2. Przekieruj użytkownika na stronę authorizationUrl.
    res.redirect(authorizationUrl);

HTTP/REST

Przykładowe przekierowanie do serwera autoryzacji Google

Przykładowy adres URL poniżej prosi o dostęp offline (access_type=offline) do zakresu, który umożliwia wyświetlanie konta YouTube użytkownika. Używa ona stopniowego autoryzowania, aby zapewnić, że nowy token dostępu obejmuje wszystkie zakresy, do których użytkownik wcześniej przyznał aplikacji dostęp. Adres URL ustawia też wartości wymaganych parametrów redirect_uri, response_typeclient_id oraz parametru state. Adres URL zawiera podziały wierszy i spacje, aby ułatwić czytelność.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

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

Serwer OAuth 2.0 Google uwierzytelnia użytkownika i uzyskiwanie od niego zgody na dostęp Twojej aplikacji do żądanych zakresów. Odpowiedź jest wysyłana z powrotem do aplikacji za pomocą podanego przez Ciebie adresu URL przekierowania.

Krok 3. Google prosi użytkownika o zgodę

Na tym etapie użytkownik decyduje, czy przyznać Twojej aplikacji wymagany dostęp. Na tym etapie Google wyświetla okno zgody, w którym podaje nazwę aplikacji i usługi interfejsu API Google, do której chce uzyskać dostęp, wraz z danymi autoryzującymi użytkownika oraz podsumowaniem zakresów dostępu. Użytkownik może wyrazić zgodę na przyznanie dostępu do co najmniej 1 zakresu żądanego przez Twoją aplikację lub odrzucić prośbę.

Na tym etapie aplikacja nie musi nic robić, ponieważ czeka na odpowiedź z serwera OAuth 2.0 Google, która wskazuje, czy przyznano dostęp. Odpowiedź na to pytanie znajdziesz w następnym kroku.

Błędy

Żądania do punktu końcowego autoryzacji OAuth 2.0 Google mogą wyświetlać komunikaty o błędach 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 1 żądanego zakresu uprawnień z powodu zasad administratora Google Workspace. Więcej informacji o tym, jak administrator może ograniczyć dostęp do wszystkich zakresów lub zakresów poufnych i ograniczonych, dopóki nie zostanie wyraźnie przyznany dostęp do Twojego identyfikatora klienta OAuth, znajdziesz w artykule pomocy dla administratorów Google Workspace Control which third-party & internal apps access Google Workspace data.

disallowed_useragent

Punkt końcowy autoryzacji jest wyświetlany w ramach wbudowanego użytkownika-agenta, który jest niedozwolony przez zasady OAuth 2.0 Google.

Android

Deweloperzy aplikacji na Androida mogą zobaczyć ten komunikat o błędzie podczas otwierania żądań autoryzacji w android.webkit.WebView. Deweloperzy powinni zamiast tego używać bibliotek Androida, takich jak Logowanie przez Google na Androida czy AppAuth na Androida od OpenID Foundation.

Deweloperzy mogą napotkać ten błąd, gdy aplikacja na Androida otwiera ogólny link internetowy w osadzonym user-agent i użytkownik przechodzi na punkt końcowy autoryzacji OAuth 2 Google z Twojej witryny. Deweloperzy powinni zezwolić na otwieranie ogólnych linków w domyślnym obsłudze linków systemu operacyjnego, co obejmuje zarówno obsługę linków aplikacji na Androida, jak i domyślną aplikację przeglądarki. Biblioteka kart niestandardowych Androida jest też obsługiwaną opcją.

iOS

Deweloperzy 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 Google Sign-In na iOS czy AppAuth na iOS od OpenID Foundation.

Deweloperzy witryn mogą napotkać ten błąd, gdy aplikacja na iOS lub macOS otwiera ogólny link internetowy w osadzonym user-agent i użytkownik przechodzi do punktu autoryzacji OAuth 2.0 Google z Twojej witryny. Deweloperzy powinni zezwolić na otwieranie ogólnych linków w domyślnym obsłudze linków systemu operacyjnego, który obejmuje zarówno obsługę linków uniwersalnych, jak i domyślną aplikację przeglądarki. Biblioteka SFSafariViewController jest też obsługiwaną opcją.

org_internal

Identyfikator klienta OAuth w żądaniu należy do projektu, który ogranicza dostęp do kont Google w określonej organizacji Google Cloud. Więcej informacji o tej opcji konfiguracji znajdziesz w sekcji Typ użytkownika w artykule pomocy Konfigurowanie ekranu zgody OAuth.

invalid_client

Tajny klucz klienta OAuth jest nieprawidłowy. Sprawdź konfigurację klienta OAuth, w tym identyfikator klienta i klucz tajny użyte w tej prośbie.

invalid_grant

Podczas odświeżania tokena dostępu lub korzystania z autoryzacji stopniowej token może być nieważny lub wygasł. Użytkownik musi się ponownie uwierzytelnić i wyrazić zgodę na uzyskanie nowych tokenów. Jeśli ten błąd będzie się powtarzał, sprawdź, czy aplikacja jest prawidłowo skonfigurowana i czy używasz w żądaniu prawidłowych tokenów i parametrów. W przeciwnym razie konto użytkownika mogło zostać usunięte lub wyłączone.

redirect_uri_mismatch

Wartość redirect_uri przekazana w żądaniu autoryzacji nie odpowiada autoryzowanemu identyfikatorowi URI przekierowania dla identyfikatora klienta OAuth. Sprawdź autoryzowane identyfikatory URI przekierowania w sekcji Google API Console Credentials page.

Parametr redirect_uri może odnosić się do przesyłania poza pasmem (OOB) w ramach protokołu OAuth, które zostało wycofane i nie jest już obsługiwane. Aby zaktualizować integrację, zapoznaj się z przewodnikiem po migracji.

invalid_request

Coś poszło nie tak z Twoją prośbą. Może to wynikać z kilku powodów:

  • żądanie jest nieprawidłowo sformatowane;
  • Brak wymaganych parametrów w prośbie
  • Żądanie używa metody autoryzacji, której Google nie obsługuje. Sprawdź, czy integracja OAuth używa 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 zaakceptuje 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 zwrócony do serwera WWW jest widoczny w ciagu zapytania, jak pokazano poniżej:

Odpowiedź błędu:

https://oauth2.example.com/auth?error=access_denied

Odpowiedź na kod 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 prosi o dostęp tylko do odczytu w celu wyświetlania metadanych plików na Dysku Google oraz dostęp tylko do odczytu w celu wyświetlania wydarzeń w Kalendarzu Google:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

Po zakończeniu procesu OAuth 2.0 powinieneś zostać przekierowany na adres http://localhost/oauth2callback, który prawdopodobnie spowoduje błąd 404 NOT FOUND, chyba że na Twoim komputerze lokalnym znajduje się plik pod tym adresem. Następny krok zapewnia więcej szczegółów o informacjach zwróconych w identyfikatorze URI, gdy użytkownik zostanie przekierowany z powrotem do 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 zamienić 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 zamienić kod autoryzacji w tej odpowiedzi na token dostępu:

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/youtube.force-ssl'],
    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 do adresu URL, który pierwotnie poprosił o autoryzację. Oznacza to odroczenie wymiany kodu przez tymczasowe przechowywanie wyników w sesji użytkownika.

  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url

Node.js

Aby zamienić 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  API Console Credentials page.
client_secret Tajny klucz klienta uzyskany z  API Console Credentials page.
code Kod autoryzacji zwrócony w odpowiedzi na początkowe żądanie.
grant_type Zgodnie ze specyfikacją OAuth 2.0 wartość tego pola musi wynosić authorization_code.
redirect_uri Jeden z identyfikatorów URI przekierowania podanych w przypadku Twojego projektu w sekcji API Console Credentials page w przypadku danego client_id.

Ten fragment kodu pokazuje 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 Twoja aplikacja ustawia parametr access_type na offline w pierwotnym żądaniu do serwera autoryzacji Google.

Odpowiedź zawiera te pola:

Pola
access_token Token wysyłany przez aplikację w celu autoryzacji żądania interfejsu Google API.
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 czasu, gdy użytkownik anuluje dostęp. Ponownie to pole jest obecne w tej odpowiedzi tylko wtedy, gdy w początkowej prośbie do serwera autoryzacji Google ustawisz parametr access_type na offline.
scope Zakresy dostępu przyznane przez access_token wyrażone jako lista rozróżniających wielkość liter ciągów znaków oddzielonych spacjami.
token_type Typ zwróconego tokena. Obecnie wartość tego pola zawsze wynosiBearer.

Ten fragment kodu pokazuje przykładową odpowiedź:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/youtube.force-ssl",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

Błędy

Podczas wymiany kodu autoryzacji na token dostępu zamiast oczekiwanej odpowiedzi możesz zobaczyć ten błąd: Poniżej znajdziesz listę typowych kodów błędów i sugerowane rozwiązania.

invalid_grant

Podany kod autoryzacji jest nieprawidłowy lub ma nieprawidłowy format. Poproś o nowy kod, rozpoczynając ponownie proces OAuth, aby ponownie poprosić użytkownika o wyrażenie zgody.

Krok 6. Sprawdź, jakie zakresy przyznali użytkownicy

Gdy żądasz kilku zakresów uprawnień naraz, użytkownicy mogą nie przyznać wszystkich zakresów, których potrzebuje Twoja aplikacja. Aplikacja powinna zawsze sprawdzać, jakie zakresy zostały przyznane przez użytkownika, i reagować na odmowę przyznania zakresów, wyłączając odpowiednie funkcje. Więcej informacji znajdziesz w artykule Zarządzanie szczegółowymi uprawnieniami.

PHP

Aby sprawdzić, jakie zakresy zostały przyznane przez użytkownika, użyj metody getGrantedScope():

// Space-separated string of granted scopes if it exists, otherwise null.
$granted_scopes = $client->getOAuth2Service()->getGrantedScope();

Python

Zwrócony obiekt credentials ma właściwość granted_scopes, która jest listą zakresów uprawnień przyznanych przez użytkownika 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}

Ruby

Gdy żądasz kilku zakresów uprawnień jednocześnie, sprawdź, które zakresy zostały przyznane za pomocą właściwości scope obiektu credentials.

# User authorized the request. Now, check which scopes were granted.
if credentials.scope.include?(Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL)
  # User authorized permission to see, edit, and permanently delete the
  # YouTube videos, ratings, comments and captions.
  # Calling the APIs, etc
else
  # User didn't authorize the permission.
  # Update UX and application accordingly
end

Node.js

Gdy żądasz kilku zakresów uprawnień jednocześnie, sprawdź, które zakresy zostały przyznane za pomocą właściwości scope obiektu tokens.

// User authorized the request. Now, check which scopes were granted.
if (tokens.scope.includes('https://www.googleapis.com/auth/youtube.force-ssl'))
{
  // User authorized permission to see, edit, and permanently delete the
  // YouTube videos, ratings, comments and captions.
  // Calling the APIs, etc.
}
else
{
  // User didn't authorize read-only Drive activity permission.
  // Update UX and application accordingly
}

HTTP/REST

Aby sprawdzić, czy użytkownik przyznał aplikacji dostęp do określonego zakresu, sprawdź pole scope w odpowiedzi na żądanie tokena dostępu. Zakresy dostępu przyznawane przez token dostępu w postaci listy ciągów znaków oddzielonych spacjami, w których rozróżniane są wielkość liter.

Na przykład ta przykładowa odpowiedź na żądanie tokena dostępu wskazuje, że użytkownik przyznał Twojej aplikacji uprawnienia do przeglądania, edytowania i trwałego usuwania filmów, ocen, komentarzy i napisów użytkownika w YouTube:

  {
    "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
    "expires_in": 3920,
    "token_type": "Bearer",
    "scope": "https://www.googleapis.com/auth/youtube.force-ssl",
    "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
  }

Wywoływanie interfejsów API Google

PHP

Aby użyć tokena dostępu do wywołania interfejsów Google API, wykonaj te czynności:

  1. Jeśli chcesz zastosować token dostępu do nowego obiektu Google\Client (np. jeśli został on 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 tworzysz, przekazując autoryzowany obiekt Google\Client do konstruktora interfejsu API, który chcesz wywołać. Aby na przykład wywołać interfejs YouTube Data API:
    $youtube = new Google_Service_YouTube($client);
  3. Wysyłać żądania do usługi interfejsu API za pomocą interfejsu udostępnionego przez obiekt usługi. Aby na przykład pobrać dane o kanale YouTube autoryzowanego użytkownika:
    $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));

Python

Po uzyskaniu tokena dostępu aplikacja może go używać do autoryzowania żądań interfejsu API w imieniu danego konta użytkownika lub konta usługi. Użyj danych autoryzujących konkretnego użytkownika, aby utworzyć obiekt usługi dla interfejsu API, który chcesz wywołać, a potem użyj tego obiektu do autoryzowania żądań interfejsu API.

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzysz, wywołując metodę googleapiclient.discovery biblioteki build z nazwą i wersją interfejsu API oraz danymi logowania użytkownika:
    from googleapiclient.discovery import build
    
    youtube = build('youtube', 'v3', credentials=credentials)
  2. Wysyłać żądania do usługi interfejsu API za pomocą interfejsu udostępnionego przez obiekt usługi. Aby na przykład pobrać dane o kanale YouTube autoryzowanego użytkownika:
    channel = youtube.channels().list(mine=True, part='snippet').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 autoryzujących konkretnego użytkownika, aby utworzyć obiekt usługi dla interfejsu API, który chcesz wywołać, a potem użyj tego obiektu do autoryzowania żądań interfejsu API.

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Aby na przykład wywołać wersję 3 interfejsu YouTube Data API:
    youtube = Google::Apis::YoutubeV3::YouTubeService.new
  2. Ustaw dane uwierzytelniające w usłudze:
    youtube.authorization = credentials
  3. Wysyłać żądania do usługi interfejsu API za pomocą interfejsu udostępnionego przez obiekt usługi. Aby na przykład pobrać dane o kanale YouTube autoryzowanego użytkownika:
    channel = youtube.list_channels(part, :mine => mine)

Autoryzację można też uzyskać w ramach poszczególnych metod, podając parametr options:

channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })

Node.js

Po uzyskaniu tokena dostępu i przypisaniu go do obiektu OAuth2 możesz używać 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świetlenia nazw plików na Dysku użytkownika.

const { google } = require('googleapis');

// Example of using YouTube API to list channels.
var service = google.youtube('v3');
service.channels.list({
  auth: oauth2Client,
  part: 'snippet,contentDetails,statistics',
  forUsername: 'GoogleDevelopers'
}, function (err, response) {
  if (err) {
    console.log('The API returned an error: ' + err);
    return;
  }
  var channels = response.data.items;
  if (channels.length == 0) {
    console.log('No channel found.');
  } else {
    console.log('This channel\'s ID is %s. Its title is \'%s\', and ' +
      'it has %s views.',
      channels[0].id,
      channels[0].snippet.title,
      channels[0].statistics.viewCount);
  }
});

HTTP/REST

Gdy aplikacja uzyska token dostępu, możesz używać tego tokena do wywoływania interfejsów API Google w imieniu danego konta użytkownika, jeśli przyznano uprawnienia dostępu wymagane przez interfejs API. Aby to zrobić, dodaj token dostępu do żądania do interfejsu API, podając parametr zapytania access_token lub wartość nagłówka HTTP Authorization Bearer. Jeśli to możliwe, zalecamy użycie nagłówka HTTP, ponieważ ciągi znaków zapytania są zwykle widoczne w dziennikach serwera. W większości przypadków możesz użyć biblioteki klienta, aby skonfigurować wywołania interfejsów API Google (np. wywołując YouTube Data API).

Pamiętaj, że interfejs YouTube Data API obsługuje konta usługowe tylko w przypadku właścicieli treści w YouTube, którzy są właścicielami wielu kanałów YouTube i nimi zarządzają, np. wytwórni muzycznych czy studiów filmowych.

Możesz wypróbować wszystkie interfejsy API Google i wyświetlić ich zakresy na stronie OAuth 2.0 Playground.

Przykłady żądań HTTP GET

Wywołanie punktu końcowego youtube.channels (interfejsu YouTube Data API) za pomocą nagłówka HTTP Authorization: Bearer może wyglądać tak: Pamiętaj, że musisz podać własny token dostępu:

GET /youtube/v3/channels?part=snippet&mine=true 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/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

curl przykładu

Te polecenia możesz przetestować za pomocą aplikacji wiersza poleceń curl. Oto przykład użycia opcji nagłówka HTTP (preferowana):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true

Możesz też użyć parametru ciągu zapytania:

curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

Pełny przykład

W tym przykładzie wypisuje obiekt w formacie JSON zawierający informacje o kanale YouTube użytkownika po jego uwierzytelnieniu i autoryzowaniu aplikacji do zarządzania kontem YouTube.

PHP

Aby uruchomić ten przykład:

  1. W sekcji API Consoledodaj adres URL lokalnego komputera do listy adresów URL przekierowań. Dodaj na przykład 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ą Composera:
    composer require google/apiclient:^2.15.0
  4. Utwórz pliki index.phpoauth2callback.php z podaną niżej 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']);
  
  $youtube = new Google_Service_YouTube($client);
  $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));
  echo json_encode($channel);
  
}
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_YOUTUBE::YOUTUBE_FORCE_SSL);

// 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();
  
  $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 frameworka Flask. Uruchom aplikację internetową na stronie http://localhost:8080, aby przetestować przepływ OAuth 2.0. Po kliknięciu tego adresu URL zobaczysz 5 linków:

  • Testowanie żądania interfejsu API: ten link prowadzi do strony, która próbuje wykonać przykładowe żądanie interfejsu API. W razie potrzeby rozpoczyna proces autoryzacji. Jeśli operacja się powiedzie, na stronie wyświetli się odpowiedź interfejsu API.
  • Testowanie procesu uwierzytelniania bezpośrednio: ten link prowadzi do strony, która próbuje przekierować użytkownika do procesu autoryzacji. Aplikacja prosi o przyznanie uprawnień do przesyłania autoryzowanych żądań interfejsu API w imieniu użytkownika.
  • Anuluj bieżące dane logowania: ten link prowadzi do strony, na której unieważniasz uprawnienia, które użytkownik już przyznał aplikacji.
  • Wyczyść dane logowania sesji Flask: ten link usuwa dane logowania uwierzytelniające, które są przechowywane w sesji Flask. Dzięki temu możesz sprawdzić, co się stanie, jeśli użytkownik, który już przyznał uprawnienia Twojej aplikacji, spróbuje wykonać w nowej sesji żądanie interfejsu API. Dzięki temu możesz też zobaczyć odpowiedź interfejsu API, którą Twoja aplikacja otrzymałaby, gdyby użytkownik cofnąłby jej uprawnienia, a aplikacja nadal próbowałaby autoryzować żądanie przy użyciu 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/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'

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('/test')
def test_api_request():
  if 'credentials' not in flask.session:
  return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  youtube = googleapiclient.discovery.build(
    API_SERVICE_NAME, API_VERSION, credentials=credentials)

  channel = youtube.channels().list(mine=True, part='snippet').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(**channel)
@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
  
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.redirect(flask.url_for('test_api_request'))
  

@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 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 frameworka Sinatra.

require 'googleauth'
require 'googleauth/web_user_authorizer'
require 'googleauth/stores/redis_token_store'

require 'google/apis/youtube_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 retrieving data about the user's YouTube channel.
  scope = 'Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL'

  # 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 read-only YouTube Data API permission.
  # Example of using YouTube Data API to list user's YouTube channel
  youtube = Google::Apis::YoutubeV3::YouTubeService.new
  channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })
  
  "<pre>#{JSON.pretty_generate(channel.to_h)}</pre>"
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 lokalnego komputera do listy adresów URL przekierowań. Na przykład:http://localhost.
  2. Upewnij się, że masz zainstalowaną wersję LTS w ramach konserwacji, aktywną wersję LTS lub najnowszą wersję Node.js.
  3. Utwórz nowy katalog i przejdź do niego. Na przykład:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. Zainstaluj bibliotekę klienta interfejsu Google API dla Node.js za pomocą npm:
    npm install googleapis
  5. Utwórz pliki main.js z podaną niżej 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 YouTube API
const scopes = [
  'https://www.googleapis.com/auth/youtube.force-ssl'
];

/* 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;
      
      // Example of using YouTube API to list channels.
      var service = google.youtube('v3');
      service.channels.list({
        auth: oauth2Client,
        part: 'snippet,contentDetails,statistics',
        forUsername: 'GoogleDevelopers'
      }, function (err, response) {
        if (err) {
          console.log('The API returned an error: ' + err);
          return;
        }
        var channels = response.data.items;
        if (channels.length == 0) {
          console.log('No channel found.');
        } else {
          console.log('This channel\'s ID is %s. Its title is \'%s\', and ' +
            'it has %s views.',
            channels[0].id,
            channels[0].snippet.title,
            channels[0].statistics.viewCount);
        }
      });
    }
  });

  // 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 korzysta z platformy Flask i biblioteki Requests, aby zademonstrować proces internetowy OAuth 2.0. W tym przypadku zalecamy użycie biblioteki klienta interfejsu API Google dla języka Python. (Przykład na karcie Python korzysta z biblioteki klienta).

import json
import flask
import requests

app = flask.Flask(__name__)

# To get these credentials (CLIENT_ID CLIENT_SECRET) and for your application, visit
# https://console.cloud.google.com/apis/credentials.
CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app

# Access scopes for YouTube API
SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl'

# 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: 
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/youtube/v3/channels/list'
    r = requests.get(req_uri, headers=headers)
    return r.text 

@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 ich aplikacji, Google stosuje do identyfikatorów URI przekierowania te reguły sprawdzania. Identyfikatory URI przekierowania muszą być zgodne z tymi zasadami. Definicje wymienionych poniżej terminów: domena, host, ścieżka, zapytanie, schemat i userinfo znajdziesz w sekcji 3 specyfikacji RFC 3986.

Reguły weryfikacji
Schemat

Identyfikatory URI przekierowania muszą używać schematu HTTPS, a nie zwykłego HTTP. Identyfikatory URI localhost (w tym identyfikatory URI adresów IP localhost) są wyłączone z zasięgu tej reguły.

Osoba prowadząca

Hostami nie mogą być zwykłe adresy IP. Z tej reguły wyłączone są adresy IP lokalnego hosta.

Domena
  • Domeny najwyższego poziomu (TLD) hosta muszą należeć do listy domen publicznych.
  • Domeny hosta nie mogą mieć wartości “googleusercontent.com”.
  • Identyfikatory URI przekierowania nie mogą zawierać domen skróconych adresów URL (np. goo.gl), chyba że domena należy do aplikacji. Jeśli aplikacja, która jest właścicielem domeny skróty, zdecyduje się na przekierowanie do tej domeny, identyfikator URI przekierowania musi zawierać “/google-callback/” w ścieżce lub kończyć się na “/google-callback”.
  • Informacje o użytkowniku

    Identyfikatory URI przekierowania nie mogą zawierać podelementu userinfo.

    Ścieżka

    Identyfikatory URI przekierowania nie mogą zawierać przemierzania ścieżki (zwanego też cofaniem się do katalogu), które jest reprezentowane przez “/..” 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ć pewnych znaków, w tym:
    • Symbole wieloznaczne ('*')
    • Niedrukowalne znaki ASCII
    • Nieprawidłowe kodowanie procentów (dowolne kodowanie procentów, które nie jest zgodne z formatem kodowania adresów URL, czyli nie zawiera znaku procenta i 2 cyfr szesnastkowych)
    • 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. W ramach najlepszej praktyki dotyczącej komfortu użytkowników należy poprosić o autoryzację zasobów w chwili, gdy są one potrzebne. Aby umożliwić tę praktykę, serwer autoryzacji Google obsługuje autoryzację przyrostową. Ta funkcja umożliwia żądanie zakresów w miarę potrzeby, a jeśli użytkownik przyzna uprawnienia do nowego zakresu, zwraca kod autoryzacji, który można wymienić na token zawierający wszystkie zakresy przyznane przez użytkownika projektowi.

    Załóżmy na przykład, że aplikacja pomaga użytkownikom w identyfikowaniu interesujących wydarzeń lokalnych. Aplikacja umożliwia użytkownikom oglądanie filmów o wydarzeniach, ocenianie filmów i dodawanie ich do playlist. Użytkownicy mogą też używać aplikacji do dodawania wydarzeń do swoich Kalendarzy Google.

    W takim przypadku podczas logowania się aplikacja może nie wymagać dostępu do żadnych zakresów lub nie żądać takiego dostępu. Jeśli jednak użytkownik spróbuje ocenić film, dodać film do playlisty lub wykonać inną czynność w YouTube, aplikacja może poprosić o dostęp w zakresie https://www.googleapis.com/auth/youtube.force-ssl. Podobnie aplikacja może poprosić o dostęp do zakresu https://www.googleapis.com/auth/calendar, jeśli użytkownik spróbuje dodać wydarzenie w kalendarzu.

    Aby wdrożyć autoryzację cząstkową, wykonaj normalny proces żądania tokena dostępu, ale upewnij się, że żądanie autoryzacji zawiera wcześniej przyznane zakresy. Dzięki temu nie musisz zarządzać wieloma tokenami dostępu.

    W przypadku tokena dostępu uzyskanego z autoryzacji stopniowej obowiązują te reguły:

    • Token może służyć do uzyskiwania dostępu do zasobów odpowiadających zakresom włączonym do nowej, połączonej autoryzacji.
    • Gdy użyjesz tokena odświeżania do autoryzacji połączonej, aby uzyskać token dostępu, token dostępu będzie reprezentować autoryzację połączoną i może być użyty do dowolnej wartościscope zawartej w odpowiedzi.
    • Połączona autoryzacja obejmuje wszystkie zakresy dostępu przyznane przez użytkownika projektowi interfejsu API, nawet jeśli prośby o te uprawnienia zostały wysłane z różnych klientów. Jeśli na przykład użytkownik przyznał dostęp do jednego zakresu za pomocą klienta aplikacji na komputer, a następnie przyznał inny zakres do tej samej aplikacji za pomocą klienta mobilnego, połączone upoważnienie będzie obejmować oba zakresy.
    • Jeśli cofniesz token reprezentujący autoryzację łączoną, dostęp do wszystkich zakresów autoryzacji w imieniu powiązanego użytkownika zostanie cofnięta jednocześnie.

    Przykłady kodu w różnych językach w sekcji Krok 1. Ustaw parametry autoryzacji oraz przykładowy adres URL przekierowania HTTP/REST w sekcji Krok 2. Przekieruj na serwer OAuth 2.0 korzystają z autoryzacji stopniowej. Przykłady kodu poniżej zawierają też kod, który musisz dodać, aby korzystać z autoryzacji cząstkowej.

    PHP

    $client->setIncludeGrantedScopes(true);

    Python

    W Pythonie ustaw argument include_granted_scopes na true, aby zapytanie o autoryzację zawierało wcześniej przyznane zakresy. Jest bardzo prawdopodobne, że include_granted_scopes nie będzie jedynym ustawionym przez Ciebie argumentem słowa kluczowego, jak pokazano w przykładzie poniżej.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    Ruby

    auth_client.update!(
      :additional_parameters => {"include_granted_scopes" => "true"}
    )

    Node.js

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });

    HTTP/REST

    W tym przykładzie aplikacja wywołująca prosi o dostęp do danych użytkownika w Analytics w YouTube, oprócz innych uprawnień, które użytkownik już przyznał aplikacji.

    GET https://accounts.google.com/o/oauth2/v2/auth?
      scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
      access_type=offline&
      state=security_token%3D138rk%3Btarget_url%3Dhttp...index&
      redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
      response_type=code&
      client_id=client_id&
      include_granted_scopes=true
    
          

    Refreshing an access token (offline access)

    Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.

    • If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
    • If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.

    Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present. The default style of access is called online.

    Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.

    PHP

    If your application needs offline access to a Google API, set the API client's access type to offline:

    $client->setAccessType("offline");

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

    Python

    W Pythonie ustaw argument access_type na offline, aby mieć możliwość odświeżania tokena dostępu bez konieczności ponownego prośby o pozwolenie od użytkownika. Jest bardzo prawdopodobne, że access_type nie będzie jedynym argumentem słowa kluczowego, jak w przykładzie poniżej.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

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

    Ruby

    Jeśli aplikacja potrzebuje dostępu do interfejsu API Google w trybie offline, ustaw typ dostępu klienta API na:offline:

    auth_client.update!(
      :additional_parameters => {"access_type" => "offline"}
    )

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

    Node.js

    Jeśli aplikacja potrzebuje dostępu do interfejsu API Google w trybie offline, ustaw typ dostępu klienta API na:offline:

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });

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

    Tokeny dostępu wygasają. Jeśli token dostępu ma wygasnąć, biblioteka automatycznie użyje tokenu odświeżania, aby uzyskać nowy token dostępu. Aby zawsze przechowywać najnowsze tokeny, możesz użyć zdarzenia „tokens”:

    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 tokena występuje tylko podczas pierwszej autoryzacji. Aby otrzymać token odświeżania, musisz ustawić parametr access_type na offline podczas wywoływania metody generateAuthUrl. Jeśli aplikacja ma już wymagane uprawnienia, ale nie ma ustawionych 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 otrzyma token odświeżania, tokeny dostępu będą pobierane 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 Tajny klucz klienta uzyskany z  API Console.
    grant_type Zgodnie z specyfikacją OAuth 2.0 wartość tego pola musi wynosić refresh_token.
    refresh_token Token odświeżania zwrócony z wymiany kodu autoryzacji.

    Ten fragment kodu pokazuje 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 przyznanego aplikacji dostępu, serwer tokenów zwraca obiekt JSON zawierający nowy token dostępu. Ten fragment kodu pokazuje przykładową odpowiedź:

    {
      "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3920,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
      "token_type": "Bearer"
    }

    Pamiętaj, że liczba wydawanych tokenów odświeżania jest ograniczona. Jeden limit dotyczy kombinacji klient/użytkownik, a drugi – wszystkich klientów. Tokeny odświeżania należy zapisać w długoterminowym magazynie danych i nadal z nich korzystać, dopóki są ważne. Jeśli aplikacja wysyła zbyt dużo żądań dotyczących 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 aplikacji. Użytkownik może cofnąć dostęp, otwierając Ustawienia konta. Więcej informacji znajdziesz w sekcji Usuwanie dostępu strony lub aplikacji do Twojego konta w dokumentacji pomocy Strony internetowe i aplikacje innych firm z dostępem do Twojego konta.

    Aplikacja może też automatycznie cofnąć przyznany dostęp. Automatyczne odwoływanie jest ważne w przypadkach, gdy użytkownik zrezygnuje z subskrypcji, usunie aplikację lub zasoby interfejsu API wymagane przez aplikację ulegną znacznym zmianom. Innymi słowy, część procesu usuwania może obejmować żądanie interfejsu API, aby usunąć uprawnienia wcześniej przyznane aplikacji.

    PHP

    Aby programowo unieważnić token, wywołaj funkcję revokeToken():

    $client->revokeToken();

    Python

    Aby programowo unieważnić token, wyślij żądanie do adresu https://oauth2.googleapis.com/revoke, dodając token jako parametr i ustawiając 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 cofnąć token, wyślij żądanie HTTP do punktu końcowego oauth2.revoke:

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)

    Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania zostanie również cofnięty.

    Jeśli odwołanie zostało przetworzone, kod stanu odpowiedzi to 200. W przypadku błędów zwracany jest kod stanu 400 oraz kod błędu.

    Node.js

    Aby programowo cofnąć token, wyślij żądanie HTTPS POST do punktu końcowego /revoke:

    const https = require('https');
    
    // Build the string for the POST request
    let postData = "token=" + userCredential.access_token;
    
    // Options for POST request to Google's OAuth 2.0 server to revoke a token
    let postOptions = {
      host: 'oauth2.googleapis.com',
      port: '443',
      path: '/revoke',
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
      }
    };
    
    // Set up the request
    const postReq = https.request(postOptions, function (res) {
      res.setEncoding('utf8');
      res.on('data', d => {
        console.log('Response: ' + d);
      });
    });
    
    postReq.on('error', error => {
      console.log(error)
    });
    
    // Post the request with data
    postReq.write(postData);
    postReq.end();

    Parametr tokena może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania zostanie również cofnięty.

    Jeśli odwołanie zostało przetworzone, kod stanu odpowiedzi to 200. W przypadku błędów zwracany jest kod stanu 400 oraz kod błędu.

    HTTP/REST

    Aby programowo unieważnić token, aplikacja wysyła żądanie do interfejsu https://oauth2.googleapis.com/revoke, dołączając token jako parametr:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania zostanie również cofnięty.

    Jeśli odwołanie zostało przetworzone, kod stanu HTTP odpowiedzi to 200. W przypadku błędów zwracany jest kod stanu HTTP 400 oraz kod błędu.

    Wdrażanie Ochrony wszystkich kont

    Dodatkowym krokiem, który należy wykonać, aby chronić konta użytkowników, jest wdrożenie ochrony na wielu kontach za pomocą usługi Google Cross-Account Protection. 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. Następnie możesz podjąć odpowiednie działania w zależności od tego, jak chcesz reagować na zdarzenia.

    Przykłady typów zdarzeń wysyłanych do Twojej aplikacji przez usługę ochrony na wielu kontach:

    • 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 oraz pełną listę dostępnych zdarzeń znajdziesz na stronie Ochrona kont użytkowników za pomocą ochrony wszystkich kont .