Questo documento spiega in che modo le applicazioni server web utilizzano le librerie client delle API di Google o gli endpoint Google OAuth 2.0 per implementare l'autorizzazione OAuth 2.0 e accedere all'API YouTube Data.
OAuth 2.0 consente agli utenti di condividere dati specifici con un'applicazione, mantenendo privati i nomi utente, le password e altre informazioni. Ad esempio, un'applicazione può utilizzare OAuth 2.0 per ottenere l'autorizzazione a caricare video sul canale YouTube di un utente.
Questo flusso OAuth 2.0 è specifico per l'autorizzazione dell'utente. È progettata per applicazioni in grado di archiviare informazioni riservate e mantenere lo stato. Un'applicazione server web correttamente autorizzata può accedere a un'API mentre l'utente interagisce con l'applicazione o dopo che l'utente ha abbandonato l'applicazione.
Le applicazioni server web utilizzano spesso anche
account di servizio per autorizzare le richieste API, in particolare quando si chiamano API Cloud per accedere a dati basati su progetti anziché a dati specifici degli utenti. Le applicazioni server web possono utilizzare account di servizio
insieme all'autorizzazione utente.
Tieni presente che l'API YouTube Data supporta il flusso dell'account di servizio solo per i proprietari dei contenuti di YouTube che possiedono e gestiscono più canali YouTube.
In particolare, i proprietari dei contenuti possono utilizzare gli account di servizio per richiamare metodi API che supportano il parametro di richiesta onBehalfOfContentOwner
.
Librerie client
Gli esempi specifici per i linguaggi in questa pagina utilizzano le librerie client delle API di Google per implementare l'autorizzazione OAuth 2.0. Per eseguire gli esempi di codice, devi prima installare la libreria client per il tuo linguaggio.
Quando utilizzi una libreria client dell'API di Google per gestire il flusso OAuth 2.0 della tua applicazione, la libreria client esegue molte azioni che l'applicazione altrimenti dovrebbe gestire autonomamente. Ad esempio, determina quando l'applicazione può utilizzare o aggiornare i token di accesso archiviati, nonché quando l'applicazione deve riacquisire il consenso. Inoltre, la libreria client genera URL di reindirizzamento corretti e aiuta a implementare gestori di reindirizzamento che scambiano i codici di autorizzazione con i token di accesso.
Le librerie client delle API di Google per le applicazioni lato server sono disponibili nei seguenti linguaggi:
Prerequisiti
Abilita le API per il progetto
Qualsiasi applicazione che chiama le API di Google deve abilitare queste API in API Console.
Per abilitare un'API per il tuo progetto:
- Open the API Library in Google API Console.
- If prompted, select a project, or create a new one.
- Utilizza la pagina Raccolta per trovare e attivare l'API YouTube Data. Trova e abilita anche le altre API utilizzate dalla tua applicazione.
Crea credenziali di autorizzazione
Qualsiasi applicazione che utilizza OAuth 2.0 per accedere alle API di Google deve avere credenziali di autorizzazione che identificano l'applicazione sul server OAuth 2.0 di Google. I passaggi seguenti spiegano come creare le credenziali per il tuo progetto. Le applicazioni possono quindi utilizzare le credenziali per accedere alle API abilitate per il progetto.
- Go to the Credentials page.
- Fai clic su Crea credenziali > ID client OAuth.
- Seleziona il tipo di applicazione Web Application.
- Compila il modulo e fai clic su Crea. Le applicazioni che utilizzano linguaggi e framework
come PHP, Java, Python, Ruby e .NET devono specificare gli URI di reindirizzamento autorizzati. Gli
URI di reindirizzamento sono gli endpoint a cui il server OAuth 2.0 può inviare risposte. Questi endpoint devono rispettare le regole di convalida di Google.
Per il test, puoi specificare gli URI che fanno riferimento alla macchina locale, ad esempio
http://localhost:8080
. Alla luce di ciò, tieni presente che tutti gli esempi in questo documento utilizzanohttp://localhost:8080
come URI di reindirizzamento.Ti consigliamo di progettare gli endpoint di autenticazione dell'app in modo che l'applicazione non esponga i codici di autorizzazione ad altre risorse della pagina.
Dopo aver creato le credenziali, scarica il file client_secret.json da API Console. Archivia il file in modo sicuro in una posizione accessibile solo dalla tua applicazione.
Identifica gli ambiti di accesso
Gli ambiti consentono all'applicazione di richiedere l'accesso solo alle risorse di cui ha bisogno, permettendo al contempo agli utenti di controllare il livello di accesso che concedono all'applicazione. Pertanto, potrebbe esistere una relazione inversa tra il numero di ambiti richiesti e la probabilità di ottenere il consenso degli utenti.
Prima di iniziare a implementare l'autorizzazione OAuth 2.0, ti consigliamo di identificare gli ambiti a cui la tua app dovrà disporre dell'autorizzazione per accedere.
Consigliamo inoltre di fare in modo che la tua applicazione richieda l'accesso agli ambiti di autorizzazione tramite un processo di autorizzazione incrementale, in cui l'applicazione richiede l'accesso ai dati utente nel contesto. Questa best practice aiuta gli utenti a comprendere più facilmente perché la tua applicazione ha bisogno dell'accesso richiesto.
La YouTube Data API v3 utilizza i seguenti ambiti:
Mirini con ingrandimento | |
---|---|
https://www.googleapis.com/auth/youtube | Gestisci il tuo account YouTube |
https://www.googleapis.com/auth/youtube.channel-memberships.creator | Visualizzare un elenco dei tuoi attuali membri attivi del canale, il loro livello corrente e quando sono diventati membri |
https://www.googleapis.com/auth/youtube.force-ssl | Visualizzare, modificare ed eliminare definitivamente video, valutazioni, commenti e sottotitoli di YouTube |
https://www.googleapis.com/auth/youtube.readonly | Visualizza il tuo account YouTube |
https://www.googleapis.com/auth/youtube.upload | Gestisci i tuoi video su YouTube |
https://www.googleapis.com/auth/youtubepartner | Visualizzare e gestire le risorse e i relativi contenuti su YouTube |
https://www.googleapis.com/auth/youtubepartner-channel-audit | Visualizzare le informazioni private del tuo canale YouTube pertinenti durante la procedura di revisione con un partner di YouTube |
Il documento Ambiti API OAuth 2.0 contiene un elenco completo degli ambiti che potresti utilizzare per accedere alle API di Google.
Requisiti specifici della lingua
Per eseguire uno qualsiasi degli esempi di codice in questo documento, devi disporre di un Account Google, dell'accesso a internet e di un browser web. Se utilizzi una delle librerie client API, consulta anche i requisiti specifici del linguaggio riportati di seguito.
PHP
Per eseguire gli esempi di codice PHP in questo documento, ti serviranno:
- PHP 5.6 o versioni successive con l'interfaccia a riga di comando (CLI) e l'estensione JSON installate.
- Lo strumento di gestione delle dipendenze di Composer.
-
Libreria client delle API di Google per PHP:
composer require google/apiclient:^2.10
Python
Per eseguire gli esempi di codice Python in questo documento, avrai bisogno di:
- Python 2.6 o versioni successive
- Lo strumento di gestione dei pacchetti pip.
- La libreria client delle API di Google per Python:
pip install --upgrade google-api-python-client
google-auth
,google-auth-oauthlib
egoogle-auth-httplib2
per l'autorizzazione dell'utente.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- Il framework dell'applicazione web Python Flask.
pip install --upgrade flask
- La libreria HTTP
requests
.pip install --upgrade requests
Ruby
Per eseguire gli esempi di codice Ruby in questo documento, avrai bisogno di:
- Ruby 2.6 o versione successiva
-
La libreria di autenticazione Google per Ruby:
gem install googleauth
-
Il framework dell'applicazione web Ruby di Sinatra.
gem install sinatra
Node.js
Per eseguire gli esempi di codice Node.js in questo documento, avrai bisogno di:
- L'LTS di manutenzione, LTS attivo o la release corrente di Node.js.
-
Il client Node.js delle API di Google:
npm install googleapis crypto express express-session
HTTP/REST
Non è necessario installare alcuna libreria per poter chiamare direttamente gli endpoint OAuth 2.0.
Ottenere i token di accesso OAuth 2.0
I passaggi seguenti mostrano in che modo la tua applicazione interagisce con il server OAuth 2.0 di Google per ottenere il consenso di un utente a eseguire una richiesta API per suo conto. La tua applicazione deve avere questo consenso prima di poter eseguire una richiesta API di Google che richiede l'autorizzazione dell'utente.
L'elenco riportato di seguito riassume rapidamente questi passaggi:
- L'applicazione identifica le autorizzazioni di cui ha bisogno.
- L'applicazione reindirizza l'utente a Google insieme all'elenco delle autorizzazioni richieste.
- Sarà l'utente a decidere se concedere le autorizzazioni alla tua applicazione.
- La tua applicazione scopre cosa ha deciso l'utente.
- Se l'utente ha concesso le autorizzazioni richieste, la tua applicazione recupera i token necessari per effettuare richieste API per conto dell'utente.
Passaggio 1: imposta i parametri di autorizzazione
Il primo passaggio consiste nel creare la richiesta di autorizzazione. Quella richiesta imposta parametri che identificano la tua applicazione e definiscono le autorizzazioni che all'utente verrà chiesto di concedere all'applicazione.
- Se utilizzi una libreria client di Google per l'autenticazione e l'autorizzazione OAuth 2.0, devi creare e configurare un oggetto che definisce questi parametri.
- Se chiami direttamente l'endpoint OAuth 2.0 di Google, genererai un URL e imposterai i parametri su quell'URL.
Le schede seguenti definiscono i parametri di autorizzazione supportati per le applicazioni server web. Gli esempi specifici per i linguaggi mostrano anche come utilizzare una libreria client o una libreria di autorizzazione per configurare un oggetto che imposta questi parametri.
PHP
Lo snippet di codice riportato di seguito crea un oggetto Google\Client()
, che definisce i parametri nella richiesta di autorizzazione.
Questo oggetto utilizza le informazioni contenute nel file client_secret.json per identificare la tua
applicazione. (Vedi Creazione di credenziali di autorizzazione per ulteriori informazioni su questo file.) L'oggetto identifica anche gli ambiti per i quali l'applicazione richiede l'autorizzazione ad accedere e l'URL dell'endpoint di autenticazione dell'applicazione, che gestirà la risposta dal server OAuth 2.0 di Google. Infine, il codice imposta i parametri facoltativi access_type
e include_granted_scopes
.
Ad esempio, questo codice richiede l'accesso offline per gestire l'account YouTube di un utente:
$client = new Google\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
Il seguente snippet di codice utilizza il modulo google-auth-oauthlib.flow
per creare la richiesta di autorizzazione.
Il codice genera un oggetto Flow
, che identifica l'applicazione utilizzando le informazioni del file client_secret.json scaricato dopo la creazione delle credenziali di autorizzazione. Questo oggetto identifica anche gli ambiti per i quali l'applicazione richiede l'autorizzazione ad accedere e l'URL dell'endpoint di autenticazione dell'applicazione, che gestirà la risposta dal server OAuth 2.0 di Google. Infine, il codice imposta i parametri facoltativi access_type
e include_granted_scopes
.
Ad esempio, questo codice richiede l'accesso offline per gestire l'account YouTube di un utente:
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
Utilizza il file client_secrets.json che hai creato per configurare un oggetto client nella tua applicazione. Quando configuri un oggetto client, specifichi gli ambiti a cui l'applicazione deve accedere, insieme all'URL dell'endpoint di autenticazione dell'applicazione, che gestirà la risposta dal server OAuth 2.0.
Ad esempio, questo codice richiede l'accesso offline per gestire l'account YouTube di un utente:
require 'google/apis/youtube_v3' require "googleauth" require 'googleauth/stores/redis_token_store' client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') scope = 'https://www.googleapis.com/auth/youtube.force-ssl' token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')
L'applicazione utilizza l'oggetto client per eseguire le operazioni OAuth 2.0, ad esempio generare URL delle richieste di autorizzazione e applicare token di accesso alle richieste HTTP.
Node.js
Il seguente snippet di codice crea un oggetto google.auth.OAuth2
, che definisce i parametri nella richiesta di autorizzazione.
Questo oggetto utilizza le informazioni del file client_secret.json per identificare l'applicazione. Per chiedere a un utente le autorizzazioni per recuperare un token di accesso, devi reindirizzarlo a una pagina di consenso. Per creare l'URL di una pagina per il consenso:
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 read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.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 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 });
Nota importante: il refresh_token
viene restituito solo alla prima autorizzazione. Ulteriori dettagli
qui.
HTTP/REST
L'endpoint OAuth 2.0 di Google si trova all'indirizzo https://accounts.google.com/o/oauth2/v2/auth
. Questo endpoint è accessibile solo tramite HTTPS. Le connessioni HTTP semplici vengono rifiutate.
Il server di autorizzazione di Google supporta i seguenti parametri di stringa di query per le applicazioni server web:
Parametri | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
client_id |
Obbligatorio
L'ID client dell'applicazione. Puoi trovare questo valore nella sezione API Console Credentials page. |
||||||||||||||||
redirect_uri |
Obbligatorio
Determina dove il server API reindirizza l'utente dopo che questo ha completato il flusso di autorizzazione. Il valore deve corrispondere esattamente a uno degli URI di reindirizzamento autorizzati per il client OAuth 2.0, che hai configurato in API Console
Credentials pagedel client. Se questo valore non corrisponde a un URI di reindirizzamento autorizzato per il Tieni presente che lo schema |
||||||||||||||||
response_type |
Obbligatorio
Determina se l'endpoint Google OAuth 2.0 restituisce un codice di autorizzazione. Imposta il valore del parametro su |
||||||||||||||||
scope |
Obbligatorio
Un elenco di ambiti delimitato da spazi che identificano le risorse a cui l'applicazione potrebbe accedere per conto dell'utente. Questi valori determinano la schermata di consenso che Google mostra all'utente. Gli ambiti consentono all'applicazione di richiedere l'accesso solo alle risorse di cui ha bisogno, permettendo al contempo agli utenti di controllare il livello di accesso che concedono all'applicazione. Pertanto, esiste una relazione inversa tra il numero di ambiti richiesti e la probabilità di ottenere il consenso degli utenti. La YouTube Data API v3 utilizza i seguenti ambiti:
Il documento Ambiti API OAuth 2.0 fornisce un elenco completo degli ambiti che potresti utilizzare per accedere alle API di Google. Consigliamo alla tua applicazione di richiedere l'accesso agli ambiti di autorizzazione nel contesto, quando possibile. Richiedendo l'accesso ai dati utente nel contesto tramite l'autorizzazione incrementale, aiuti gli utenti a comprendere più facilmente perché la tua applicazione ha bisogno dell'accesso richiesto. |
||||||||||||||||
access_type |
Consigliato
Indica se la tua applicazione può aggiornare i token di accesso quando l'utente non è presente nel browser. I valori validi del parametro sono Imposta il valore su |
||||||||||||||||
state |
Consigliato
Specifica qualsiasi valore stringa utilizzato dall'applicazione per mantenere lo stato tra la richiesta di autorizzazione e la risposta del server di autorizzazione.
Il server restituisce il valore esatto che invii come coppia Puoi utilizzare questo parametro per diversi scopi, ad esempio indirizzare l'utente alla risorsa corretta nell'applicazione, inviare nonce e ridurre la falsificazione delle richieste tra siti. Poiché |
||||||||||||||||
include_granted_scopes |
Facoltativo
Consente alle applicazioni di utilizzare l'autorizzazione incrementale per richiedere l'accesso ad ambiti aggiuntivi nel contesto. Se imposti il valore di questo parametro su |
||||||||||||||||
enable_granular_consent |
Facoltativo
Il valore predefinito è Quando Google abilita autorizzazioni granulari per un'applicazione, questo parametro non avrà più alcun effetto. |
||||||||||||||||
login_hint |
Facoltativo
Se la tua applicazione sa quale utente sta tentando di eseguire l'autenticazione, può utilizzare questo parametro per fornire un suggerimento al server di autenticazione di Google. Il server utilizza il suggerimento per semplificare il flusso di accesso precompilando il campo email nel modulo di accesso o selezionando la sessione con accesso multiplo appropriata. Imposta il valore del parametro su un indirizzo email o un identificatore |
||||||||||||||||
prompt |
Facoltativo
Un elenco di richieste per presentare all'utente, delimitato da spazi, e sensibile alle maiuscole. Se non specifichi questo parametro, all'utente verrà richiesto l'accesso solo la prima volta che il tuo progetto richiede l'accesso. Per maggiori informazioni, consulta la sezione Richiedere un nuovo consenso. I valori possibili sono:
|
Passaggio 2: reindirizza al server OAuth 2.0 di Google
Reindirizza l'utente al server OAuth 2.0 di Google per avviare il processo di autenticazione e autorizzazione. In genere, questo si verifica quando l'applicazione deve prima accedere ai dati dell'utente. Nel caso dell'autorizzazione incrementale, questo passaggio si verifica anche quando l'applicazione deve prima accedere a risorse aggiuntive a cui non è ancora autorizzata ad accedere.
PHP
- Genera un URL per richiedere l'accesso al server OAuth 2.0 di Google:
$auth_url = $client->createAuthUrl();
- Reindirizza l'utente a
$auth_url
:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
Questo esempio mostra come reindirizzare l'utente all'URL di autorizzazione utilizzando il framework per applicazioni web Flask:
return flask.redirect(authorization_url)
Ruby
- Genera un URL per richiedere l'accesso al server OAuth 2.0 di Google:
auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
- Reindirizza l'utente a
auth_uri
.
Node.js
-
Utilizza l'URL generato
authorizationUrl
dal metodogenerateAuthUrl
del Passaggio 1 per richiedere l'accesso al server OAuth 2.0 di Google. -
Reindirizza l'utente a
authorizationUrl
.res.redirect(authorizationUrl);
HTTP/REST
Sample redirect to Google's authorization server
The sample URL below requests offline access
(access_type=offline
) to a scope that permits access to view
the user's YouTube account. It uses incremental authorization to ensure that
the new access token covers any scopes to which the user previously granted
the application access. The URL also sets values for the required
redirect_uri
, response_type
, and
client_id
parameters as well as for the state
parameter. The URL contains line breaks and spaces for readability.
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
Dopo aver creato l'URL della richiesta, reindirizza l'utente a quest'ultimo.
Il server OAuth 2.0 di Google autentica l'utente e ottiene il consenso dell'utente affinché la tua applicazione acceda agli ambiti richiesti. La risposta viene inviata alla tua applicazione utilizzando l'URL di reindirizzamento specificato.
Passaggio 3: Google richiede il consenso all'utente
In questo passaggio, l'utente deciderà se concedere alla tua applicazione l'accesso richiesto. In questa fase, Google mostra una finestra di consenso che mostra il nome della tua applicazione e dei servizi API di Google per i quali richiede l'autorizzazione ad accedere con le credenziali di autorizzazione dell'utente e un riepilogo degli ambiti di accesso da concedere. L'utente può quindi acconsentire alla concessione dell'accesso a uno o più ambiti richiesti dalla tua applicazione o rifiutare la richiesta.
L'applicazione non deve fare nulla in questa fase perché attende la risposta dal server OAuth 2.0 di Google che indica se è stato concesso un accesso. Questa risposta è spiegata nel passaggio seguente.
Errori
Le richieste all'endpoint di autorizzazione OAuth 2.0 di Google potrebbero visualizzare messaggi di errore rivolti agli utenti anziché i flussi di autenticazione e autorizzazione previsti. Di seguito sono elencati i codici di errore comuni e le soluzioni suggerite.
admin_policy_enforced
L'Account Google non è in grado di autorizzare uno o più ambiti richiesti a causa dei criteri dell'amministratore di Google Workspace. Consulta l'articolo del Centro assistenza per amministratori di Google Workspace Specificare quali app di terze parti e interne possono accedere ai dati di Google Workspace per saperne di più su come un amministratore può limitare l'accesso a tutti gli ambiti o agli ambiti sensibili e con restrizioni finché l'accesso non viene concesso esplicitamente all'ID client OAuth.
disallowed_useragent
L'endpoint di autorizzazione viene visualizzato all'interno di uno user agent incorporato non consentito dai criteri OAuth 2.0 di Google.
Android
Gli sviluppatori Android potrebbero visualizzare questo messaggio di errore quando aprono le richieste di autorizzazione in
android.webkit.WebView
.
Gli sviluppatori devono invece usare librerie Android come
Accedi con Google per Android o
AppAuth per Android di OpenID Foundation.
Gli sviluppatori web potrebbero riscontrare questo errore quando un'app per Android apre un link web generale in uno user agent incorporato e un utente accede all'endpoint di autorizzazione OAuth 2.0 di Google dal tuo sito. Gli sviluppatori devono consentire l'apertura dei link generali nel gestore di link predefinito del sistema operativo, che include sia i gestori Link per app Android sia l'app browser predefinita. È supportata anche la raccolta Schede personalizzate Android.
iOS
Gli sviluppatori iOS e macOS potrebbero riscontrare questo errore quando aprono le richieste di autorizzazione in
WKWebView
.
Gli sviluppatori devono invece utilizzare librerie iOS come
Accedi con Google per iOS o
AppAuth per iOS di OpenID Foundation.
Gli sviluppatori web potrebbero riscontrare questo errore quando un'app per iOS o macOS apre un link web generale in uno user agent incorporato e un utente accede all'endpoint di autorizzazione OAuth 2.0 di Google dal tuo sito. Gli sviluppatori devono consentire l'apertura dei link generali nel gestore di link predefinito del sistema operativo, che include sia i gestori Universal Links sia l'app browser predefinita. È supportata anche la libreria SFSafariViewController
.
org_internal
L'ID client OAuth nella richiesta fa parte di un progetto che limita l'accesso agli Account Google in una specifica organizzazione Google Cloud. Per maggiori informazioni su questa opzione di configurazione, consulta la sezione Tipo di utente nell'articolo del Centro assistenza Configurare la schermata per il consenso OAuth.
invalid_client
Il client secret OAuth non è corretto. Esamina la configurazione del client OAuth, inclusi l'ID client e il secret utilizzati per questa richiesta.
invalid_grant
Quando aggiorni un token di accesso o utilizzi l'autorizzazione incrementale, il token potrebbe essere scaduto o essere stato invalidato. Autentica di nuovo l'utente e richiedi il consenso dell'utente per ottenere nuovi token. Se continui a visualizzare questo errore, assicurati che l'applicazione sia stata configurata correttamente e di utilizzare i token e i parametri corretti nella richiesta. In caso contrario, l'account utente potrebbe essere stato eliminato o disattivato.
redirect_uri_mismatch
Il valore redirect_uri
trasmesso nella richiesta di autorizzazione non corrisponde a un URI di reindirizzamento autorizzato per l'ID client OAuth. Esamina gli URI di reindirizzamento autorizzati in
Google API Console Credentials page.
Il parametro redirect_uri
potrebbe fare riferimento al flusso OAuth out-of-band (OOB) che è stato
deprecato e non è più supportato. Consulta la
guida alla migrazione per aggiornare la tua
integrazione.
invalid_request
Si è verificato un problema nella richiesta che hai inviato. Ciò potrebbe essere dovuto a una serie di motivi:
- La richiesta non è formattata correttamente
- Nella richiesta mancano dei parametri obbligatori
- La richiesta utilizza un metodo di autorizzazione non supportato da Google. Verifica che l'integrazione OAuth utilizzi un metodo di integrazione consigliato
Passaggio 4: gestisci la risposta del server OAuth 2.0
Il server OAuth 2.0 risponde alla richiesta di accesso della tua applicazione utilizzando l'URL specificato nella richiesta.
Se l'utente approva la richiesta di accesso, la risposta contiene un codice di autorizzazione. Se l'utente non approva la richiesta, la risposta contiene un messaggio di errore. Il codice di autorizzazione o il messaggio di errore che viene restituito al server web viene visualizzato nella stringa di query, come mostrato di seguito:
Una risposta di errore:
https://oauth2.example.com/auth?error=access_denied
Una risposta da un codice di autorizzazione:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
Esempio di risposta del server OAuth 2.0
Puoi testare questo flusso facendo clic sul seguente URL di esempio, che richiede l'accesso in sola lettura per visualizzare i metadati dei file nel tuo Google Drive:
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
Dopo aver completato il flusso OAuth 2.0, dovresti essere reindirizzato a http://localhost/oauth2callback
, il che probabilmente restituirà un errore 404 NOT FOUND
, a meno che la macchina locale non pubblichi un file a quell'indirizzo. Il passaggio successivo fornisce ulteriori dettagli sulle informazioni restituite nell'URI quando l'utente viene reindirizzato alla tua applicazione.
Passaggio 5: scambia il codice di autorizzazione per i token di aggiornamento e di accesso
Dopo che il server web ha ricevuto il codice di autorizzazione, può scambiarlo con un token di accesso.
PHP
Per scambiare un codice di autorizzazione con un token di accesso, utilizza il metodo authenticate
:
$client->authenticate($_GET['code']);
Puoi recuperare il token di accesso con il metodo getAccessToken
:
$access_token = $client->getAccessToken();
Python
Nella pagina di callback, utilizza la libreria google-auth
per verificare la risposta del server di autorizzazione. Quindi, utilizza il metodo flow.fetch_token
per scambiare il codice di autorizzazione in quella risposta con un token di accesso:
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, 'scopes': credentials.scopes}
Ruby
Nella pagina di callback, utilizza la libreria googleauth
per verificare la risposta del server
di autorizzazione. Utilizza il metodo authorizer.handle_auth_callback_deferred
per salvare il codice di autorizzazione e reindirizzare all'URL che ha richiesto l'autorizzazione in origine. Questo
ritarda lo scambio del codice archiviando temporaneamente i risultati nella sessione dell'utente.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
Per scambiare un codice di autorizzazione con un token di accesso, utilizza il metodo 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
Per scambiare un codice di autorizzazione con un token di accesso, chiama l'endpoint
https://oauth2.googleapis.com/token
e imposta i seguenti parametri:
Campi | |
---|---|
client_id |
L'ID client ottenuto da API Console Credentials page. |
client_secret |
Il client secret ottenuto da API Console Credentials page. |
code |
Il codice di autorizzazione restituito dalla richiesta iniziale. |
grant_type |
Come definito nella specifica OAuth 2.0, il valore di questo campo deve essere impostato su authorization_code . |
redirect_uri |
Uno degli URI di reindirizzamento elencati per il tuo progetto in
API Console
Credentials page per il
client_id specificato. |
Lo snippet seguente mostra una richiesta di esempio:
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
Google risponde a questa richiesta restituendo un oggetto JSON che contiene un token di accesso di breve durata e un token di aggiornamento.
Tieni presente che il token di aggiornamento viene restituito solo se l'applicazione ha impostato il parametro access_type
su offline
nella richiesta iniziale al server di autorizzazione di Google.
La risposta contiene i seguenti campi:
Campi | |
---|---|
access_token |
Il token che l'applicazione invia per autorizzare una richiesta API di Google. |
expires_in |
La durata rimanente del token di accesso in secondi. |
refresh_token |
Un token che puoi utilizzare per ottenere un nuovo token di accesso. I token di aggiornamento sono validi finché l'utente non revoca l'accesso.
Anche in questo caso, questo campo è presente in questa risposta solo se imposti il parametro access_type
su offline nella richiesta iniziale al server di autorizzazione di Google.
|
scope |
Gli ambiti di accesso concessi da access_token espressi come elenco di stringhe delimitate da spazi e sensibili alle maiuscole. |
token_type |
Il tipo di token restituito. Al momento, il valore di questo campo è sempre impostato su Bearer . |
Lo snippet seguente mostra una risposta di esempio:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/youtube.force-ssl", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
Errori
Quando cambi il codice di autorizzazione con un token di accesso, potresti riscontrare il seguente errore anziché la risposta prevista. Di seguito sono elencati i codici di errore comuni e le soluzioni suggerite.
invalid_grant
Il codice di autorizzazione fornito non è valido o è nel formato errato. Richiedi un nuovo codice riavviando il processo OAuth per richiedere nuovamente il consenso all'utente.
Chiamata alle API di Google
PHP
Utilizza il token di accesso per chiamare le API di Google, completando i seguenti passaggi:
- Se devi applicare un token di accesso a un nuovo oggetto
Google\Client
, ad esempio se lo hai archiviato in una sessione utente, utilizza il metodosetAccessToken
:$client->setAccessToken($access_token);
- Crea un oggetto di servizio per l'API che vuoi chiamare. Per creare un oggetto di servizio, devi fornire un oggetto
Google\Client
autorizzato al costruttore dell'API che vuoi chiamare. Ad esempio, per chiamare l'API YouTube Data:$youtube = new Google_Service_YouTube($client);
- Effettua le richieste al servizio API utilizzando l'interfaccia fornita dall'oggetto di servizio.
Ad esempio, per recuperare i dati relativi al canale YouTube dell'utente autorizzato:
$channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));
Python
Dopo aver ottenuto un token di accesso, l'applicazione può utilizzarlo per autorizzare le richieste API per conto di un determinato account utente o di servizio. Utilizza le credenziali di autorizzazione specifiche dell'utente per creare un oggetto di servizio per l'API che vuoi chiamare, quindi utilizza l'oggetto per effettuare le richieste API autorizzate.
- Crea un oggetto di servizio per l'API che vuoi chiamare. Puoi creare un oggetto di servizio chiamando il metodo
build
della libreriagoogleapiclient.discovery
con il nome e la versione dell'API e le credenziali utente: Ad esempio, per chiamare la versione 3 dell'API YouTube Data:from googleapiclient.discovery import build youtube = build('youtube', 'v3', credentials=credentials)
- Effettua le richieste al servizio API utilizzando l'interfaccia fornita dall'oggetto di servizio.
Ad esempio, per recuperare i dati relativi al canale YouTube dell'utente autorizzato:
channel = youtube.channels().list(mine=True, part='snippet').execute()
Ruby
Dopo aver ottenuto un token di accesso, l'applicazione può utilizzarlo per effettuare richieste API per conto di un determinato account utente o di servizio. Utilizza le credenziali di autorizzazione specifiche dell'utente per creare un oggetto di servizio per l'API che vuoi chiamare, quindi utilizza l'oggetto per effettuare le richieste API autorizzate.
- Crea un oggetto di servizio per l'API che vuoi chiamare.
Ad esempio, per chiamare la versione 3 dell'API YouTube Data:
youtube = Google::Apis::YoutubeV3::YouTubeService.new
- Imposta le credenziali sul servizio:
youtube.authorization = credentials
- Effettua le richieste al servizio API utilizzando l'interfaccia fornita dall'oggetto di servizio.
Ad esempio, per recuperare i dati relativi al canale YouTube dell'utente autorizzato:
channel = youtube.list_channels(part, :mine => mine)
In alternativa, l'autorizzazione può essere fornita in base al metodo fornendo il parametro options
a un metodo:
channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })
Node.js
Dopo aver ottenuto un token di accesso e averlo impostato nell'oggetto OAuth2
, utilizza l'oggetto per chiamare le API di Google. L'applicazione può utilizzare il token per autorizzare le richieste API per conto di un determinato account utente o di servizio. Crea un oggetto di servizio per l'API che vuoi chiamare.
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
Dopo che l'applicazione ha ottenuto un token di accesso, puoi utilizzarlo per effettuare chiamate a un'API di Google per conto di un determinato account utente, se sono stati concessi gli ambiti di accesso richiesti dall'API. Per farlo, includi il token di accesso in una richiesta all'API includendo un parametro di query access_token
o un valore Bearer
dell'intestazione HTTP Authorization
. Se possibile, è preferibile utilizzare l'intestazione HTTP, in quanto le stringhe di query tendono a essere visibili nei log del server. Nella maggior parte dei casi puoi utilizzare una libreria client per configurare le chiamate alle API di Google (ad esempio, quando chiami l'API YouTube Data).
Tieni presente che la YouTube Data API supporta gli account di servizio solo per i proprietari di contenuti YouTube che possiedono e gestiscono più canali YouTube, come le case discografiche e gli studi cinematografici.
Puoi provare tutte le API di Google e visualizzarne gli ambiti nel OAuth 2.0 Playground.
Esempi GET HTTP
Una chiamata all'endpoint
youtube.channels
(l'API YouTube Data) utilizzando l'intestazione HTTP Authorization: Bearer
potrebbe essere simile alla seguente. Tieni presente che devi specificare un tuo token di accesso:
GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
Ecco una chiamata alla stessa API per l'utente autenticato utilizzando il parametro della stringa di query
access_token
:
GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
curl
esempi
Puoi testare questi comandi con l'applicazione a riga di comando curl
. Ecco un
esempio che utilizza l'opzione dell'intestazione HTTP (preferita):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true
Oppure, in alternativa, l'opzione del parametro della stringa di query:
curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
Esempio completo
L'esempio seguente mostra un oggetto in formato JSON che mostra informazioni sul canale YouTube di un utente dopo che quest'ultimo ha autenticato e autorizzato l'applicazione a gestire l'account YouTube dell'utente.
PHP
Per eseguire questo esempio:
- In API Console, aggiungi l'URL della macchina locale all'elenco degli URL di reindirizzamento. Ad esempio, aggiungi
http://localhost:8080
. - Crea una nuova directory e aprila. Ad esempio:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Installa la libreria client dell'API di Google per PHP utilizzando Composer:
composer require google/apiclient:^2.10
- Crea i file
index.php
eoauth2callback.php
con i contenuti di seguito. - Esegui l'esempio con un server web configurato per pubblicare PHP. Se utilizzi PHP 5.6 o versioni successive, puoi usare il server web di test integrato di 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_secrets.json'); $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); 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_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(); $client->setAuthConfigFile('client_secrets.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); if (! isset($_GET['code'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } $client->authenticate($_GET['code']); $_SESSION['access_token'] = $client->getAccessToken(); $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
Python
Questo esempio utilizza il framework Flask. Esegue
un'applicazione web all'indirizzo http://localhost:8080
che consente di testare il flusso
OAuth 2.0. Se accedi a quell'URL, dovresti vedere quattro link:
- Testa una richiesta API: questo link rimanda a una pagina che tenta di eseguire una richiesta API di esempio. Se necessario, avvia il flusso di autorizzazione. In caso di esito positivo, la pagina visualizza la risposta dell'API.
- Testa direttamente il flusso di autorizzazione:questo link rimanda a una pagina che tenta di indirizzare l'utente attraverso il flusso di autorizzazione. L'app richiede l'autorizzazione per inviare richieste API autorizzate per conto dell'utente.
- Revoca le credenziali attuali: questo link rimanda a una pagina che revoca le autorizzazioni che l'utente ha già concesso all'applicazione.
- Cancella credenziali di sessione Flask: questo link cancella le credenziali di autorizzazione archiviate nella sessione Flask. In questo modo puoi vedere cosa accadrebbe se un utente che aveva già concesso l'autorizzazione alla tua app tentasse di eseguire una richiesta API in una nuova sessione. Consente inoltre di vedere la risposta API ricevuta dall'app se un utente avesse revocato le autorizzazioni concesse all'app e l'app tentasse comunque di autorizzare una richiesta con un token di accesso revocato.
# -*- 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" # This OAuth 2.0 access scope allows for full read/write 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, 'scopes': credentials.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' # 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
Questo esempio utilizza il framework Sinatra.
require 'google/apis/youtube_v3' require 'sinatra' require 'googleauth' require 'googleauth/stores/redis_token_store' configure do enable :sessions set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback') end get '/' do user_id = settings.client_id.id credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request) end 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 get '/oauth2callback' do target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
Per eseguire questo esempio:
-
In API Console, aggiungi l'URL della
macchina locale all'elenco degli URL di reindirizzamento. Ad esempio, aggiungi
http://localhost
. - Assicurati di avere installato LTS di manutenzione, LTS attivo o la release corrente di Node.js.
-
Crea una nuova directory e aprila. Ad esempio:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
Install the
Google API Client
Library
for Node.js using npm:
npm install googleapis
-
Crea il file
main.js
con i contenuti seguenti. -
Esegui l'esempio:
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 read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.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 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 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.'); } }); } }); // 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(80); } main().catch(console.error);
HTTP/REST
Questo esempio Python utilizza il framework Flask e la libreria Requests per dimostrare il flusso web OAuth 2.0. Per questo flusso, consigliamo di utilizzare la libreria client dell'API di Google per Python. (l'esempio nella scheda Python utilizza la libreria client).
import json import flask import requests app = flask.Flask(__name__) CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl' 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 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'} 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()
Regole di convalida dell'URI di reindirizzamento
Google applica le seguenti regole di convalida agli URI di reindirizzamento per aiutare gli sviluppatori a proteggere le loro applicazioni. Gli URI di reindirizzamento devono ottemperare a queste regole. Consulta la sezione 3 RFC 3986 per la definizione di dominio, host, percorso, query, schema e info utente, come spiegato di seguito.
Regole di convalida | |
---|---|
Schema |
Gli URI di reindirizzamento devono utilizzare lo schema HTTPS e non il semplice HTTP. Gli URI Localhost (inclusi gli URI degli indirizzi IP localhost) sono esenti da questa regola. |
Host |
Gli host non possono essere indirizzi IP non elaborati. Gli indirizzi IP Localhost sono esenti da questa regola. |
Dominio |
“googleusercontent.com” .goo.gl ), a meno che
l'app non sia proprietaria del dominio. Inoltre, se un'app che possiede un dominio abbreviato sceglie di reindirizzare a quel dominio, l'URI di reindirizzamento deve contenere “/google-callback/” nel percorso o terminare con “/google-callback” . |
Informazioni utente |
Gli URI di reindirizzamento non possono contenere il sottocomponente userinfo. |
Percorso |
Gli URI di reindirizzamento non possono contenere un path traversal (chiamato anche backtracking della directory), rappresentato da un valore |
Query |
Gli URI di reindirizzamento non possono contenere reindirizzamenti aperti. |
Frammento |
Gli URI di reindirizzamento non possono contenere il componente del frammento. |
Caratteri |
Gli URI di reindirizzamento non possono contenere determinati caratteri, tra cui:
|
Autorizzazione incrementale
Nel protocollo OAuth 2.0, la tua app richiede l'autorizzazione per accedere alle risorse, che sono identificate dagli ambiti. È considerata una best practice per l'esperienza utente richiedere l'autorizzazione per le risorse nel momento in cui ne hai bisogno. Per abilitare questa pratica, il server di autorizzazione di Google supporta l'autorizzazione incrementale. Questa funzionalità consente di richiedere gli ambiti in base alle necessità e, se l'utente concede l'autorizzazione per il nuovo ambito, restituisce un codice di autorizzazione che può essere scambiato con un token contenente tutti gli ambiti che l'utente ha concesso al progetto.
Ad esempio, supponiamo che un'app aiuti gli utenti a identificare eventi locali interessanti. L'app consente agli utenti di visualizzare i video relativi agli eventi, valutarli e aggiungerli alle playlist. Gli utenti possono utilizzare l'app anche per aggiungere eventi ai propri calendari Google.
In questo caso, al momento dell'accesso, l'app potrebbe non aver bisogno o richiedere l'accesso ad
tutti gli ambiti. Tuttavia, se l'utente prova a valutare un video, ad aggiungerlo a una
playlist o a eseguire un'altra azione di YouTube, l'app potrebbe richiedere l'accesso
all'ambito https://www.googleapis.com/auth/youtube.force-ssl
.
Allo stesso modo, l'app potrebbe richiedere l'accesso all'ambito
https://www.googleapis.com/auth/calendar
se l'utente provava
ad aggiungere un evento di calendario.
Per implementare l'autorizzazione incrementale, devi completare il normale flusso per richiedere un token di accesso, ma assicurati che la richiesta di autorizzazione includa gli ambiti concessi in precedenza. Questo approccio consente alla tua app di evitare di dover gestire più token di accesso.
Le seguenti regole si applicano a un token di accesso ottenuto da un'autorizzazione incrementale:
- Il token può essere utilizzato per accedere alle risorse corrispondenti a qualsiasi ambito implementato nella nuova autorizzazione combinata.
- Quando utilizzi il token di aggiornamento per l'autorizzazione combinata per ottenere un token di accesso, il token di accesso rappresenta l'autorizzazione combinata e può essere utilizzato per qualsiasi valore
scope
incluso nella risposta. - L'autorizzazione combinata include tutti gli ambiti che l'utente ha concesso al progetto API anche se le concessioni sono state richieste da client diversi. Ad esempio, se un utente ha concesso l'accesso a un ambito utilizzando il client desktop di un'applicazione e poi ha concesso un altro ambito alla stessa applicazione tramite un client mobile, l'autorizzazione combinata includerà entrambi gli ambiti.
- Se revochi un token che rappresenta un'autorizzazione combinata, l'accesso a tutti gli ambiti di tale autorizzazione per conto dell'utente associato viene revocato contemporaneamente.
Gli esempi di codice specifico per la lingua nel Passaggio 1: imposta i parametri di autorizzazione e l'URL di reindirizzamento HTTP/REST di esempio nel Passaggio 2: reindirizza al server OAuth 2.0 di Google utilizzano tutti l'autorizzazione incrementale. Gli esempi di codice riportati di seguito mostrano anche il codice che devi aggiungere per utilizzare l'autorizzazione incrementale.
PHP
$client->setIncludeGrantedScopes(true);
Python
In Python, imposta l'argomento parola chiave include_granted_scopes
su true
per
garantire che una richiesta di autorizzazione includa ambiti concessi in precedenza. È molto possibile che include_granted_scopes
non sia l'unico argomento parola chiave che hai impostato, come mostrato nell'esempio di seguito.
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
In questo esempio, l'applicazione chiamante richiede l'accesso per recuperare i dati di YouTube Analytics dell'utente, in aggiunta a qualsiasi altro accesso che l'utente ha già concesso all'applicazione.
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 tooffline
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");
Dopo che un utente concede l'accesso offline agli ambiti richiesti, puoi continuare a utilizzare il client API per accedere alle API di Google per conto dell'utente quando quest'ultimo è offline. L'oggetto client aggiornerà il token di accesso in base alle esigenze.
Python
In Python, imposta l'argomento parola chiave access_type
su offline
per assicurarti di poter aggiornare il token di accesso senza dover chiedere nuovamente all'utente l'autorizzazione. È molto possibile che access_type
non sia l'unico argomento parola chiave
che hai impostato, come mostrato nell'esempio di seguito.
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')
Dopo che un utente concede l'accesso offline agli ambiti richiesti, puoi continuare a utilizzare il client API per accedere alle API di Google per conto dell'utente quando quest'ultimo è offline. L'oggetto client aggiornerà il token di accesso in base alle esigenze.
Ruby
Se l'applicazione richiede l'accesso offline a un'API di Google, imposta il tipo di accesso del client API su
offline
:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
Dopo che un utente concede l'accesso offline agli ambiti richiesti, puoi continuare a utilizzare il client API per accedere alle API di Google per conto dell'utente quando quest'ultimo è offline. L'oggetto client aggiornerà il token di accesso in base alle esigenze.
Node.js
Se l'applicazione richiede l'accesso offline a un'API di Google, imposta il tipo di accesso del client API su
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 });
Dopo che un utente concede l'accesso offline agli ambiti richiesti, puoi continuare a utilizzare il client API per accedere alle API di Google per conto dell'utente quando quest'ultimo è offline. L'oggetto client aggiornerà il token di accesso in base alle esigenze.
I token di accesso hanno una scadenza. Questa libreria utilizzerà automaticamente un token di aggiornamento per ottenere un nuovo token di accesso se sta per scadere. Un modo semplice per assicurarti di archiviare sempre i token più recenti è utilizzare l'evento dei token:
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); });
Questo evento dei token si verifica solo nella prima autorizzazione e devi aver impostato access_type
su offline
quando chiami il metodo generateAuthUrl
per ricevere il token di aggiornamento. Se hai già concesso alla tua app le autorizzazioni richieste senza impostare i vincoli appropriati per la ricezione di un token di aggiornamento, dovrai autorizzare nuovamente l'applicazione a ricevere un nuovo token di aggiornamento.
Per impostare refresh_token
in un secondo momento, puoi utilizzare il metodo setCredentials
:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
Una volta che il client dispone di un token di aggiornamento, i token di accesso verranno acquisiti e aggiornati automaticamente nella chiamata successiva all'API.
HTTP/REST
Per aggiornare un token di accesso, l'applicazione invia una richiesta POST
HTTPS al server di autorizzazione di Google (https://oauth2.googleapis.com/token
) che
include i seguenti parametri:
Campi | |
---|---|
client_id |
L'ID client ottenuto da API Console. |
client_secret |
Il client secret ottenuto da API Console. |
grant_type |
Come definito nella specifica OAuth 2.0, il valore di questo campo deve essere impostato su refresh_token . |
refresh_token |
Il token di aggiornamento restituito dallo scambio del codice di autorizzazione. |
Lo snippet seguente mostra una richiesta di esempio:
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
Se l'utente non ha revocato l'accesso concesso all'applicazione, il server token restituisce un oggetto JSON contenente un nuovo token di accesso. Lo snippet seguente mostra una risposta di esempio:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "scope": "https://www.googleapis.com/auth/drive.metadata.readonly", "token_type": "Bearer" }
Tieni presente che sono previsti dei limiti al numero di token di aggiornamento che verranno emessi: un limite per ogni combinazione client/utente e un altro per utente per tutti i client. Dovresti salvare i token di aggiornamento nello spazio di archiviazione a lungo termine e continuare a utilizzarli finché rimangono validi. Se l'applicazione richiede troppi token di aggiornamento, potrebbe imbattersi in questi limiti, nel qual caso i token di aggiornamento meno recenti smetteranno di funzionare.
Revoca di un token
In alcuni casi un utente potrebbe decidere di revocare l'accesso concesso a un'applicazione. Un utente può revocare l'accesso visitando le Impostazioni account. Per ulteriori informazioni, consulta la sezione relativa alla rimozione dell'accesso di siti o app del documento di assistenza per siti e app di terze parti con accesso al tuo account.
È anche possibile che un'applicazione revoca in modo programmatico l'accesso concesso. La revoca programmatica è importante nei casi in cui un utente annulla l'iscrizione o rimuove un'applicazione oppure le risorse API richieste da un'app sono cambiate in modo significativo. In altre parole, parte del processo di rimozione può includere una richiesta API per garantire che le autorizzazioni precedentemente concesse all'applicazione vengano rimosse.
PHP
Per revocare un token in modo programmatico, chiama revokeToken()
:
$client->revokeToken();
Python
Per revocare un token in modo programmatico, effettua una richiesta a https://oauth2.googleapis.com/revoke
che includa il token come parametro e imposti l'intestazione Content-Type
:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Ruby
Per revocare un token in modo programmatico, effettua una richiesta HTTP all'endpoint
oauth2.revoke
:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
Il token può essere un token di accesso o un token di aggiornamento. Se il token è un token di accesso e ha un token di aggiornamento corrispondente, verrà revocato anche il token di aggiornamento.
Se la revoca viene elaborata correttamente, il codice di stato della risposta è
200
. Per le condizioni di errore, viene restituito un codice di stato 400
insieme a un codice di errore.
Node.js
Per revocare un token in modo programmatico, effettua una richiesta POST HTTPS all'endpoint
/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();
Il parametro token può essere un token di accesso o un token di aggiornamento. Se il token è un token di accesso e ha un token di aggiornamento corrispondente, verrà revocato anche il token di aggiornamento.
Se la revoca viene elaborata correttamente, il codice di stato della risposta è
200
. Per le condizioni di errore, viene restituito un codice di stato 400
insieme a un codice di errore.
HTTP/REST
Per revocare un token in modo programmatico, l'applicazione invia una richiesta a https://oauth2.googleapis.com/revoke
e include il token come parametro:
curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \ https://oauth2.googleapis.com/revoke?token={token}
Il token può essere un token di accesso o un token di aggiornamento. Se il token è un token di accesso e ha un token di aggiornamento corrispondente, verrà revocato anche il token di aggiornamento.
Se la revoca viene elaborata correttamente, il codice di stato HTTP della risposta è
200
. Per le condizioni di errore, viene restituito un codice di stato HTTP 400
insieme a un codice di errore.