Utilizzo di OAuth 2.0 per le applicazioni da server a server

Il sistema OAuth 2.0 di Google supporta le interazioni server-to-server, ad esempio quelle tra un'applicazione web e un servizio Google. Per questo scenario è necessario un account di servizio, ovvero un account che appartiene all'applicazione anziché a un singolo utente finale. La tua applicazione chiama le API di Google per conto dell'account di servizio, quindi gli utenti non sono direttamente coinvolti. Questo scenario è a volte chiamato "OAuth a due passaggi" o "2LO". Il termine correlato "OAuth a tre vie" si riferisce a scenari in cui la tua applicazione chiama le API di Google per conto degli utenti finali e in cui a volte è richiesto il consenso dell'utente.

In genere, un'applicazione utilizza un account di servizio quando utilizza le API Google per lavorare con i propri dati anziché con quelli di un utente. Ad esempio, un'applicazione che utilizza Google Cloud Datastore per la persistenza dei dati utilizzerà un account di servizio per autenticare le chiamate all' API Google Cloud Datastore.

Gli amministratori di dominio di Google Workspace possono anche concedere agli account di servizio l'autorità a livello di dominio per accedere ai dati degli utenti per conto degli utenti nel dominio.

Questo documento descrive come un'applicazione può completare il flusso OAuth 2.0 da server a server utilizzando una libreria client delle API Google (opzione consigliata) o HTTP.

Panoramica

Per supportare le interazioni server-to-server, crea prima un account di servizio per il tuo progetto in API Console. Se vuoi accedere ai dati utente degli utenti nel tuo account Google Workspace, delega l'accesso a livello di dominio all'account di servizio.

L'applicazione si prepara quindi a effettuare chiamate API autorizzate utilizzando le credenziali dell'account di servizio per richiedere un token di accesso dal server di autenticazione OAuth 2.0.

Infine, l'applicazione può utilizzare il token di accesso per chiamare le API Google.

Creazione di un account di servizio

Le credenziali di un account di servizio includono un indirizzo email generato univoco e almeno una coppia di chiavi pubblica/privata. Se la delega a livello di dominio è attivata, un ID client fa parte anche delle credenziali dell'account di servizio.

Se l'applicazione viene eseguita su Google App Engine, un account di servizio viene configurato automaticamente quando crei il progetto.

Se l'applicazione viene eseguita su Google Compute Engine, viene configurato anche un account di servizio automaticamente quando crei il progetto, ma devi specificare gli ambiti a cui deve accedere la tua applicazione quando crei un'istanza Google Compute Engine. Per maggiori informazioni, consulta Preparare un'istanza per l'utilizzo degli account di servizio.

Se la tua applicazione non viene eseguita su Google App Engine o Google Compute Engine, devi ottenere queste credenziali in Google API Console. Per generare le credenziali dell'account di servizio o per visualizzare le credenziali pubbliche che hai già generato:

First, create a service account:

  1. Open the Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Click  Create service account.
  4. Under Service account details, type a name, ID, and description for the service account, then click Create and continue.
  5. Optional: Under Grant this service account access to project, select the IAM roles to grant to the service account.
  6. Click Continue.
  7. Optional: Under Grant users access to this service account, add the users or groups that are allowed to use and manage the service account.
  8. Click Done.

Next, create a service account key:

  1. Click the email address for the service account you created.
  2. Click the Keys tab.
  3. In the Add key drop-down list, select Create new key.
  4. Click Create.

Your new public/private key pair is generated and downloaded to your machine; it serves as the only copy of the private key. You are responsible for storing it securely. If you lose this key pair, you will need to generate a new one.

Puoi tornare a API Console in qualsiasi momento per visualizzare l'indirizzo email, le impronte delle chiavi pubbliche e altre informazioni oppure per generare altre coppie di chiavi pubbliche/private. Per maggiori dettagli sulle credenziali degli account di servizio in API Console, consulta Account di servizio nel file di aiuto API Console.

Prendi nota dell'indirizzo email dell'account di servizio e salva il file della chiave privata dell'account di servizio in una posizione accessibile alla tua applicazione. La tua applicazione ne ha bisogno per effettuare chiamate API autorizzate.

Delega dell'autorità a livello di dominio all'account di servizio

Utilizzando un account Google Workspace, un amministratore di Workspace dell'organizzazione può autorizzare un'applicazione ad accedere ai dati utente di Workspace per conto degli utenti del dominio Google Workspace. Ad esempio, un'applicazione che utilizza l'API Google Calendar per aggiungere eventi ai calendari di tutti gli utenti di un dominio Google Workspace utilizzerà un account di servizio per accedere all'API Google Calendar per conto degli utenti. L'autorizzazione di un account di servizio ad accedere ai dati per conto degli utenti di un dominio è talvolta indicata come "delega dell'autorità a livello di dominio" a un account di servizio.

Per delegare l'autorità a livello di dominio a un account di servizio, un super amministratore del dominio Google Workspace deve completare i seguenti passaggi:

  1. Nella Console di amministrazione del tuo dominio Google Workspace, vai a Menu principale > Sicurezza > Accesso e controllo dei dati > Controlli API.
  2. Nel riquadro Delega a livello di dominio, seleziona Gestisci delega a livello di dominio.
  3. Fai clic su Aggiungi nuova.
  4. Nel campo ID client, inserisci l'ID client dell'account di servizio. Puoi trovare l'ID client del tuo account di servizio in Service accounts page.
  5. Nel campo Ambiti OAuth (delimitati da virgole), inserisci l'elenco degli ambiti a cui deve essere concesso l'accesso alla tua applicazione. Ad esempio, se la tua applicazione richiede accesso completo all'API di Google Drive e all'API di Google Calendar a livello di dominio, inserisci: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Fai clic su Autorizza.

Ora la tua applicazione ha l'autorizzazione a effettuare chiamate API come utente del tuo dominio Workspace (per "impersonare" gli utenti). Quando ti prepari a effettuare queste chiamate API delegate, dovrai specificare esplicitamente l'utente da usurpare.

Preparazione di una chiamata API delegata

Java

Dopo aver ottenuto l'indirizzo email e la chiave privata del client da API Console, utilizza la libreria client delle API di Google per Java per creare un oggetto GoogleCredential dalle credenziali dell'account di servizio e dagli ambiti a cui la tua applicazione deve accedere. Ad esempio:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Se stai sviluppando un'app sulla piattaforma Google Cloud, puoi utilizzare le credenziali predefinite dell'applicazione per semplificare la procedura.

Delega l'autorità a livello di dominio

Se hai delegato l'accesso a livello di dominio all'account di servizio e vuoi rubare l'identità di un account utente, specifica l'indirizzo email dell'account utente con il metodo createDelegated dell'oggetto GoogleCredential. Ad esempio:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

Il codice riportato sopra utilizza l'oggetto GoogleCredential per chiamare il relativo metodo createDelegated(). L'argomento per il metodo createDelegated() deve essere un utente che appartiene al tuo account Workspace. Il codice che effettua la richiesta utilizzerà questa credenziale per chiamare le API Google utilizzando il tuo account di servizio.

Python

Dopo aver ottenuto l'indirizzo email e la chiave privata del client da API Console, utilizza la libreria client delle API di Google per Python per completare i seguenti passaggi:

  1. Crea un oggetto Credentials dalle credenziali dell'account di servizio e dagli ambiti a cui la tua applicazione deve accedere. Ad esempio:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    Se stai sviluppando un'app sulla piattaforma Google Cloud, puoi utilizzare le credenziali predefinite dell'applicazione per semplificare la procedura.

  2. Delega l'autorità a livello di dominio

    Se hai delegato l'accesso a livello di dominio all'account di servizio e vuoi assumere il ruolo di un account utente, utilizza il metodo with_subject di un oggetto ServiceAccountCredentials esistente. Ad esempio:

    delegated_credentials = credentials.with_subject('user@example.org')

Utilizza l'oggetto Credentials per chiamare le API di Google nella tua applicazione.

HTTP/REST

Dopo aver ottenuto l'ID client e la chiave privata da API Console, la tua applicazione deve completare i seguenti passaggi:

  1. Crea un token JWT (JSON Web Token, pronunciato "jot") che includa un'intestazione, un insieme di attestazioni e una firma.
  2. Richiedi un token di accesso dal server di autorizzazione OAuth 2.0 di Google.
  3. Gestisci la risposta JSON restituita dal server di autorizzazione.

Le sezioni seguenti descrivono come completare questi passaggi.

Se la risposta include un token di accesso, puoi utilizzarlo per chiamare un'API Google. Se la risposta non include un token di accesso, la richiesta JWT e del token potrebbe non essere formattata correttamente o l'account di servizio potrebbe non disporre dell'autorizzazione per accedere agli ambiti richiesti.

Quando il token di accesso scade, l'applicazione ne genera un altro, lo firma e richiede un altro token di accesso.

L'applicazione server utilizza un JWT per richiedere un token al server di autorizzazione Google, quindi utilizza il token per chiamare un endpoint dell'API Google. Non è coinvolto nessun
                                 utente finale.

Il resto di questa sezione descrive le specifiche per la creazione di un JWT, la firma del JWT, la formazione della richiesta del token di accesso e la gestione della risposta.

Creazione di un JWT

Un JWT è composto da tre parti: un'intestazione, un insieme di claim e una firma. L'intestazione e l'insieme di claim sono oggetti JSON. Questi oggetti JSON vengono serializzati in byte UTF-8, quindi codificati utilizzando la codifica Base64url. Questa codifica offre resilienza alle modifiche della codifica dovute a operazioni di codifica ripetute. L'intestazione, l'insieme di rivendicazioni e la firma vengono concatenati con un carattere punto (.).

Un JWT è composto come segue:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

La stringa di base per la firma è la seguente:

{Base64url encoded header}.{Base64url encoded claim set}
Formazione dell'intestazione JWT

L'intestazione è composta da tre campi che indicano l'algoritmo di firma, il formato della dichiarazione e l'[ID chiave della chiave dell'account di servizio](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) utilizzato per firmare il JWT. L'algoritmo e il formato sono obbligatori e ogni campo ha un solo valore. Man mano che vengono introdotti algoritmi e formati aggiuntivi, questa intestazione cambierà di conseguenza. L'ID chiave è facoltativo e, se viene specificato un ID chiave errato, Google Cloud proverà con tutte le chiavi associate all'account di servizio per verificare il token e rifiutarlo se non viene trovata alcuna chiave valida. Google si riserva il diritto di rifiutare i token con ID chiave non corretti in futuro.

Gli account di servizio si basano sull'algoritmo RSA SHA-256 e sul formato del token JWT. Di conseguenza, la rappresentazione JSON dell'intestazione è la seguente:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

La rappresentazione Base64url è la seguente:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
Formazione dell'insieme di attestazioni JWT

L'insieme di rivendicazioni JWT contiene informazioni sul JWT, tra cui le autorizzazioni richieste (scope), il target del token, l'emittente, la data e l'ora di emissione del token e la sua durata. La maggior parte dei campi è obbligatoria. Come l'intestazione JWT, l'insieme di attestazioni JWT è un oggetto JSON e viene utilizzato nel calcolo della firma.

Rivendicazioni obbligatorie

I claim obbligatori nell'insieme di claim JWT sono riportati di seguito. Possono essere visualizzati in qualsiasi ordine nel set di rivendicazioni.

Nome Descrizione
iss L'indirizzo email dell'account di servizio.
scope Un elenco delimitato da spazi delle autorizzazioni richieste dall'applicazione.
aud Un descrittore del target previsto dell'affermazione. Quando effettui una richiesta di token di accesso, questo valore è sempre https://oauth2.googleapis.com/token.
exp La data e l'ora di scadenza dell'affermazione, specificate in secondi dal 1° gennaio 1970 alle ore 00:00:00 UTC. Questo valore ha un massimo di 1 ora dopo l'ora di emissione.
iat L'ora in cui è stata emessa l'affermazione, specificata in secondi dal 1° gennaio 1970 00:00:00 UTC.

Di seguito è riportata la rappresentazione JSON dei campi obbligatori in un insieme di attestazioni JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Altre rivendicazioni

In alcuni casi aziendali, un'applicazione può utilizzare la delega a livello di dominio per agire per conto di un determinato utente di un'organizzazione. L'autorizzazione per eseguire questo tipo di furto d'identità deve essere concessa prima che un'applicazione possa rubare l'identità di un utente e in genere è gestita da un super amministratore. Per saperne di più, consulta Controllare l'accesso all'API con la delega a livello di dominio.

Per ottenere un token di accesso che concede a un'applicazione l'accesso delegato a una risorsa, includi l'indirizzo email dell'utente nell'attributo JWT impostato come valore del campo sub.

Nome Descrizione
sub L'indirizzo email dell'utente per cui l'applicazione richiede l'accesso delegato.

Se un'applicazione non dispone dell'autorizzazione per rubare l'identità di un utente, la risposta a una richiesta di token di accesso che include il campo sub sarà un errore.

Di seguito è riportato un esempio di un insieme di rivendicazioni JWT che include il campo sub:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Codifica dell'insieme di attestazioni JWT

Come l'intestazione JWT, l'insieme di attestazioni JWT deve essere serializzato in UTF-8 e codificato in Base64url. Di seguito è riportato un esempio di rappresentazione JSON di un insieme di rivendicazioni JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Calcolo della firma

JSON Web Signature (JWS) è la specifica che guida la procedura di generazione della firma per il JWT. L'input per la firma è l'array di byte dei seguenti contenuti:

{Base64url encoded header}.{Base64url encoded claim set}

L'algoritmo di firma nell'intestazione JWT deve essere utilizzato per il calcolo della firma. L'unico algoritmo di firma supportato dal server di autorizzazione OAuth 2.0 di Google è RSA con algoritmo di hashing SHA-256. Questo valore è espresso come RS256 nel campo alg dell'intestazione JWT.

Firma la rappresentazione UTF-8 dell'input utilizzando SHA256withRSA (noto anche come RSASSA-PKCS1-V1_5-SIGN con la funzione hash SHA-256) con la chiave privata ottenuta da Google API Console. L'output sarà un array di byte.

La firma deve poi essere codificata in Base64url. L'intestazione, l'insieme di rivendicazioni e la firma vengono concatenati con un carattere punto (.). Il risultato è il JWT. Deve essere visualizzato quanto segue (interruzioni di riga aggiunte per chiarezza):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

Di seguito è riportato un esempio di JWT prima della codifica Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

Di seguito è riportato un esempio di JWT firmato e pronto per la trasmissione:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Effettuare la richiesta del token di accesso

Dopo aver generato il JWT firmato, un'applicazione può utilizzarlo per richiedere un token di accesso. Questa richiesta di token di accesso è una richiesta POST HTTPS e il corpo è codificato in URL. L'URL è mostrato di seguito:

https://oauth2.googleapis.com/token

I seguenti parametri sono obbligatori nella richiesta POST HTTPS:

Nome Descrizione
grant_type Utilizza la seguente stringa, codificata in URL se necessario: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion Il JWT, inclusa la firma.

Di seguito è riportato un dump non elaborato della richiesta POST HTTPS utilizzata in una richiesta di token di accesso:

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

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

Di seguito è riportata la stessa richiesta, che utilizza curl:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Gestione della risposta

Se il JWT e la richiesta del token di accesso sono formattati correttamente e l'account di servizio ha l'autorizzazione per eseguire l'operazione, la risposta JSON del server di autorizzazione include un token di accesso. Di seguito è riportato un esempio di risposta:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

I token di accesso possono essere riutilizzati durante il periodo di durata specificato dal valore expires_in.

Chiamate alle API di Google

Java

Utilizza l'oggetto GoogleCredential per chiamare le API Google completando i seguenti passaggi:

  1. Crea un oggetto di servizio per l'API che vuoi chiamare utilizzando l'oggetto GoogleCredential. Ad esempio:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Invia richieste al servizio API utilizzando l'interfaccia fornita dall'oggetto servizio. Ad esempio, per elencare le istanze dei database Cloud SQL nel progetto exciting-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Utilizza l'oggetto Credentials autorizzato per chiamare le API di Google completando i seguenti passaggi:

  1. Crea un oggetto servizio per l'API che vuoi chiamare. Puoi creare un oggetto servizio chiamando la funzione build con il nome e la versione dell'API e l'oggetto Credentials autorizzato. Ad esempio, per chiamare la versione 1beta3 dell'API Cloud SQL Administration:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Invia richieste al servizio API utilizzando l'interfaccia fornita dall'oggetto servizio. Ad esempio, per elencare le istanze dei database Cloud SQL nel progetto exciting-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Dopo che l'applicazione ha ottenuto un token di accesso, puoi utilizzarlo per effettuare chiamate a un'API Google per conto di un determinato account di servizio o utente se gli ambiti di accesso richiesti dall'API sono stati concessi. 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 l'intestazione HTTP, perché 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 Drive Files).

Puoi provare tutte le API di Google e visualizzarne gli ambiti in OAuth 2.0 Playground.

Esempi di richieste GET HTTP

Una chiamata all'endpoint drive.files (l'API Drive Files) che utilizza l'intestazione HTTP Authorization: Bearer potrebbe avere il seguente aspetto. Tieni presente che devi specificare il tuo token di accesso:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Ecco una chiamata alla stessa API per l'utente autenticato che utilizza il parametro della stringa di query access_token:

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

curl esempi

Puoi testare questi comandi con l'applicazione a riga di comando curl. Ecco un esempio che utilizza l'opzione dell'intestazione HTTP (opzione preferita):

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

In alternativa, l'opzione del parametro stringa di query:

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

Quando scadono i token di accesso

I token di accesso emessi dal server di autorizzazione OAuth 2.0 di Google scadono dopo la durata indicata dal valore expires_in. Quando un token di accesso scade, l'applicazione deve generare un altro JWT, firmarlo e richiedere un altro token di accesso.

Codici di errore JWT

Campo error Campo error_description Significato Come risolvere il problema
unauthorized_client Unauthorized client or scope in request. Se stai tentando di utilizzare la delega a livello di dominio, l'account di servizio non è autorizzato nella Console di amministrazione del dominio dell'utente.

Assicurati che l'account di servizio sia autorizzato nella pagina Delega a livello di dominio della Console di amministrazione per l'utente nel sub claim (campo).

In genere sono sufficienti pochi minuti, ma potrebbero essere necessarie fino a 24 ore affinché l'autorizzazione si propaghi a tutti gli utenti del tuo Account Google.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Nella Console di amministrazione è stato autorizzato un account di servizio utilizzando l'indirizzo email del client anziché l'ID client (numerico). Nella pagina Delega a livello di dominio della Console di amministrazione, rimuovi il client e aggiungilo nuovamente con l'ID numerico.
access_denied (qualsiasi valore) Se utilizzi la delega a livello di dominio, uno o più ambiti richiesti non sono autorizzati nella Console di amministrazione.

Assicurati che l'account di servizio sia autorizzato nella pagina Delega a livello di dominio della Console di amministrazione per l'utente nel token (campo) sub e che includa tutti gli ambiti richiesti nel token scope del JWT.

In genere sono sufficienti pochi minuti, ma potrebbero essere necessarie fino a 24 ore affinché l'autorizzazione si propaghi a tutti gli utenti del tuo Account Google.

admin_policy_enforced (qualsiasi valore) L'Account Google non è in grado di autorizzare uno o più ambiti richiesti a causa delle norme dell'amministratore 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 limitazioni finché l'accesso non viene concesso esplicitamente al tuo ID cliente OAuth, consulta l'articolo del Centro assistenza Google Workspace Controllare quali app di terze parti e interne possono accedere ai dati di Google Workspace.

invalid_client (qualsiasi valore)

Il client OAuth o il token JWT non è valido o non è configurato correttamente.

Per maggiori dettagli, consulta la descrizione dell'errore.

Assicurati che il token JWT sia valido e contenga rivendicazioni corrette.

Verifica che l'account di servizio e il client OAuth siano configurati correttamente e che tu stia utilizzando l'indirizzo email corretto.

Verifica che il token JWT sia corretto e che sia stato emesso per l'ID cliente nella richiesta.

invalid_grant Not a valid email. L'utente non esiste. Verifica che l'indirizzo email nel reclamo sub (campo) sia corretto.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

In genere, significa che l'ora del sistema locale non è corretta. Può accadere anche se il valore exp è più lontano nel tempo rispetto al valore iat di più di 65 minuti oppure se il valore exp è inferiore al valore iat.

Assicurati che l'orologio sul sistema in cui viene generato il JWT sia corretto. Se necessario, sincronizza l'ora con Google NTP.

invalid_grant Invalid JWT Signature.

L'affermazione JWT è firmata con una chiave privata non associata all'account di servizio identificato dall'email del cliente o la chiave utilizzata è stata eliminata, disattivata o è scaduta.

In alternativa, l'affermazione JWT potrebbe essere codificata in modo errato: deve essere codificata in base64, senza interruzioni di riga o segni di uguale di riempimento.

Decodifica l'insieme di claim JWT e verifica che la chiave che ha firmato l'affermazione sia associata all'account di servizio.

Prova a utilizzare una libreria OAuth fornita da Google per assicurarti che il JWT venga generato correttamente.

invalid_scope Invalid OAuth scope or ID token audience provided. Non sono stati richiesti ambiti (elenco di ambiti vuoto) o uno degli ambiti richiesti non esiste (ovvero non è valido).

Assicurati che l'attributo (campo) scope del JWT sia compilato e confronta gli ambiti in esso contenuti con gli ambiti documentati per le API che vuoi utilizzare per assicurarti che non ci siano errori o errori ortografici.

Tieni presente che l'elenco degli ambiti nella rivendicazione scope deve essere separato da spazi, non da virgole.

disabled_client The OAuth client was disabled. La chiave utilizzata per firmare l'affermazione JWT è disattivata.

Vai a Google API Consolee in IAM e amministrazione > Account di servizio, abilita l'account di servizio contenente l'"ID chiave" utilizzato per firmare l'affermazione.

org_internal This client is restricted to users within its organization. L'ID client OAuth nella richiesta fa parte di un progetto che limita l'accesso agli Account Google in un' organizzazione Google Cloud specifica.

Utilizza un account di servizio dell'organizzazione per l'autenticazione. Conferma la configurazione del tipo di utente per la tua applicazione OAuth.

Addendum: autorizzazione dell'account di servizio senza OAuth

Con alcune API di Google, puoi effettuare chiamate API autorizzate utilizzando un JWT firmato direttamente come token di accesso, anziché un token di accesso OAuth 2.0. Se possibile, puoi evitare di dover effettuare una richiesta di rete al server di autorizzazione di Google prima di effettuare una chiamata API.

Se l'API che vuoi chiamare ha una definizione di servizio pubblicata nel repository GitHub delle API di Google, puoi effettuare chiamate API autorizzate utilizzando un JWT anziché un token di accesso. Per farlo:

  1. Crea un account di servizio come descritto sopra. Assicurati di conservare il file JSON che ricevi quando crei l'account.
  2. Utilizzando una libreria JWT standard, ad esempio quella disponibile all'indirizzo jwt.io, crea un JWT con un'intestazione e un payload come nell'esempio seguente:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • Per il campo kid nell'intestazione, specifica l'ID della chiave privata del tuo account di servizio. Puoi trovare questo valore nel campo private_key_id del file JSON dell'account di servizio.
    • Per i campi iss e sub, specifica l'indirizzo email del tuo account di servizio. Puoi trovare questo valore nel campo client_email del file JSON dell'account di servizio.
    • Per il campo aud, specifica l'endpoint API. Ad esempio: https://SERVICE.googleapis.com/.
    • Per il campo iat, specifica l'ora Unix corrente e per il campo exp, specifica l'ora esatta 3600 secondi dopo, quando il JWT scade.

Firma il JWT con RSA-256 utilizzando la chiave privata nel file JSON dell'account di servizio.

Ad esempio:

Java

Utilizzo di google-api-java-client e java-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Utilizzando PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Chiama l'API utilizzando il JWT firmato come token di accesso:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

Implementare la Protezione su più account

Un ulteriore passaggio da seguire per proteggere gli account dei tuoi utenti è implementare la protezione tra account utilizzando il servizio di protezione tra account di Google. Questo servizio ti consente di iscriverti alle notifiche relative agli eventi di sicurezza che forniscono informazioni alla tua applicazione su modifiche importanti all'account utente. Puoi quindi utilizzare le informazioni per intervenire in base a come decidi di rispondere agli eventi.

Ecco alcuni esempi di tipi di eventi inviati alla tua app dal Servizio di protezione tra account di Google:

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

Per ulteriori informazioni su come implementare la funzionalità Protezione su più account e per l'elenco completo degli eventi disponibili, consulta la pagina Proteggere gli account utente con la Protezione su più account .