Usar o OAuth 2.0 para aplicativos de servidor para servidor

Gravação Para mais informações, consulte Visão geral da autenticação na documentação do Google Cloud Platform.

O sistema do Google OAuth 2.0 oferece suporte a interações entre servidores, como aquelas entre um aplicativo da Web e um serviço do Google. Nesse caso, você precisa de uma conta de serviço, que pertence ao aplicativo, e não a um usuário final individual. O aplicativo chama APIs do Google em nome da conta de serviço para que os usuários não sejam diretamente envolvidos. Esse cenário é chamado de "OAuth de duas etapas" ou "2LO". O termo relacionado "OAuth de três etapas" se refere a cenários em que seu aplicativo chama APIs do Google em nome de usuários finais e em que às vezes o consentimento do usuário é necessário.

Normalmente, um aplicativo usa uma conta de serviço quando utiliza APIs do Google para trabalhar com os próprios dados em vez dos dados de um usuário. Por exemplo, um aplicativo que usa o Google Cloud Datastore para persistência de dados usaria uma conta de serviço para autenticar as chamadas para a API Google Cloud Datastore.

Os administradores de domínios do Google Workspace também podem conceder autoridade em todas as contas de serviço para acessar dados do usuário em nome dos usuários no domínio.

Este documento descreve como um aplicativo pode concluir o fluxo de OAuth 2.0 de servidor para servidor usando uma biblioteca de cliente das APIs do Google (recomendado) ou HTTP.

Visão geral

Para oferecer compatibilidade com interações de servidor para servidor, primeiro crie uma conta de serviço para seu projeto no . Se você quiser acessar os dados dos usuários na conta do Google Workspace, delegue o acesso em todo o domínio à conta de serviço.

Em seguida, o aplicativo se prepara para fazer chamadas de API autorizadas usando as credenciais da conta de serviço para solicitar um token de acesso do servidor de autenticação OAuth 2.0.

Por fim, o aplicativo pode usar o token de acesso para chamar as APIs do Google.

Como criar uma conta de serviço

As credenciais de uma conta de serviço incluem um endereço de e-mail gerado exclusivo e pelo menos um par de chaves públicas/privadas. Se a delegação em todo o domínio estiver ativada, um ID do cliente também fará parte das credenciais da conta de serviço.

Quando o aplicativo é executado no Google App Engine, uma conta de serviço é configurada automaticamente quando o projeto é criado.

Quando o aplicativo é executado no Google Compute Engine, uma conta de serviço também é configurada automaticamente quando o projeto é criado. No entanto, é preciso especificar os escopos a que o aplicativo precisa de acesso ao criar uma instância do Google Compute Engine. Para mais informações, consulte Como preparar uma instância para usar contas de serviço.

Se o aplicativo não for executado no Google App Engine ou no Google Compute Engine, você precisará obter essas credenciais na . Para gerar credenciais de conta de serviço ou ver as credenciais públicas que você já gerou, faça o seguinte:

Primeiro, crie uma conta de serviço:

  1. Abra o Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Clique em Criar conta de serviço .
  4. Em Detalhes da conta de serviço , digite um nome, ID e descrição para a conta de serviço e clique em Criar e continuar .
  5. Opcional: em Grant this service account access to project , selecione os papéis do IAM a serem concedidos à conta de serviço.
  6. Clique em Continuar .
  7. Opcional: em Conceder aos usuários acesso a esta conta de serviço , adicione os usuários ou grupos que têm permissão para usar e gerenciar a conta de serviço.
  8. Clique em Concluído .

Em seguida, crie uma chave de conta de serviço:

  1. Clique no endereço de e-mail da conta de serviço que você criou.
  2. Clique na guia Chaves .
  3. Na lista suspensa Adicionar chave , selecione Criar nova chave .
  4. Clique em Criar .

Seu novo par de chaves pública/privada é gerado e baixado em sua máquina; ele serve como a única cópia da chave privada. Você é responsável por armazená-lo com segurança. Se você perder esse par de chaves, precisará gerar um novo.

É possível retornar ao API Console a qualquer momento para ver o endereço de e-mail, as impressões digitais da chave pública e outras informações, ou gerar outros pares de chaves públicas/privadas. Para mais detalhes sobre as credenciais da conta de serviço no API Console, consulte Contas de serviço no arquivo de ajuda API Console.

Anote o endereço de e-mail da conta de serviço e armazene o arquivo da chave privada dela em um local acessível ao seu aplicativo. Seu aplicativo precisa deles para fazer chamadas de API autorizadas.

Delegar autoridade em todo o domínio à conta de serviço

Se você tem uma conta do Google Workspace, um administrador da organização pode autorizar um aplicativo a acessar dados em nome de usuários no domínio do Google Workspace. Por exemplo, um aplicativo que usa a API Google Calendar para adicionar eventos às agendas de todos os usuários em um domínio do Google Workspace usaria uma conta de serviço para acessar essa API em nome dos usuários. Autorizar uma conta de serviço a acessar dados em nome de usuários em um domínio é, às vezes, denominado "delegar autoridade em todo o domínio" a uma conta de serviço.

Para delegar a autoridade de todo o domínio a uma conta de serviço, um superadministrador do domínio do Google Workspace precisa concluir as seguintes etapas:

  1. No Admin Console do seu domínio do Google Workspace, acesse o Menu principal > Segurança > Acesso e controle de dados > Controles de API.
  2. No painel Delegação em todo o domínio, selecione Gerenciar a delegação em todo o domínio.
  3. clique em Add new;
  4. No campo ID do cliente, insira o ID do cliente da conta de serviço. Você encontra o ID do cliente da sua conta de serviço no Service accounts page.
  5. No campo Escopos do OAuth (delimitado por vírgulas), insira a lista de escopos aos quais o aplicativo deve receber acesso. Por exemplo, caso seu aplicativo precise de acesso total ao domínio à API Google Drive e à API Google Agenda, digite: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Clique em Autorizar.

Seu aplicativo agora tem a autoridade para fazer chamadas de API como usuários no seu domínio para "se passar por usuários". Ao se preparar para fazer chamadas de API autorizadas, especifique o usuário a ser personificado.

Como se preparar para fazer uma chamada de API autorizada

Java

Depois de conseguir o endereço de e-mail e a chave privada do cliente no API Console, use a Biblioteca de cliente das APIs do Google para Java para criar um objeto GoogleCredential com as credenciais da conta de serviço e os escopos aos quais seu aplicativo precisa de acesso. Exemplo:

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 você estiver desenvolvendo um aplicativo no Google Cloud Platform, poderá usar as credenciais padrão do aplicativo para simplificar o processo.

Delegar autoridade em todo o domínio

Se você tiver delegado o acesso em todo o domínio à conta de serviço e quiser representar uma conta de usuário, especifique o endereço de e-mail da conta de usuário com o método createDelegated do objeto GoogleCredential. Por exemplo:

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

Use o objeto GoogleCredential para chamar as APIs do Google no aplicativo.

Python

Depois de conseguir o endereço de e-mail e a chave privada do cliente no API Console, use a Biblioteca de cliente das APIs do Google para Python para concluir as seguintes etapas:

  1. Crie um objeto Credentials com as credenciais da conta de serviço e os escopos aos quais seu aplicativo precisa de acesso. Por exemplo:
    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 você estiver desenvolvendo um aplicativo no Google Cloud Platform, poderá usar as credenciais padrão do aplicativo para simplificar o processo.

  2. Delegar autoridade em todo o domínio

    Se você tiver delegado o acesso em todo o domínio à conta de serviço e quiser representar uma conta de usuário, use o método with_subject de um objeto ServiceAccountCredentials existente. Exemplo:

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

Use o objeto Credentials para chamar as APIs do Google no seu aplicativo.

HTTP/REST

Depois de conseguir o ID do cliente e a chave privada do API Console, o aplicativo precisará concluir as etapas a seguir:

  1. Crie um JSON Web Token (JWT, pronunciado, "jot") que inclua um cabeçalho, um conjunto de declarações e uma assinatura.
  2. Solicite um token de acesso ao servidor de autorização do Google OAuth 2.0.
  3. Processar a resposta JSON retornada pelo servidor de autorização.

As seções a seguir descrevem como concluir essas etapas.

Se a resposta incluir um token de acesso, será possível usá-lo para chamar uma API do Google. Se a resposta não incluir um token de acesso, talvez o JWT e a solicitação de token não estejam formatados corretamente ou a conta de serviço não tenha permissão para acessar os escopos solicitados.

Quando o token de acesso expira, o aplicativo gera outro JWT, o assina e solicita outro token de acesso.

O aplicativo do servidor usa um JWT para solicitar um token do servidor de autorização do Google e, em seguida, usa o token para chamar um endpoint da API do Google. Nenhum usuário final está envolvido.

O restante desta seção descreve os detalhes de criação de um JWT, assinatura do JWT, formação da solicitação de token de acesso e processamento da resposta.

Como criar um JWT

Um JWT é composto por três partes: um cabeçalho, um conjunto de declarações e uma assinatura. O cabeçalho e o conjunto de declarações são objetos JSON. Esses objetos JSON são serializados em bytes UTF-8 e codificados com a codificação Base64url. Essa codificação oferece resiliência a mudanças de codificação devido a operações de codificação repetidas. O cabeçalho, o conjunto de declarações e a assinatura são concatenados com um caractere de ponto (.).

Um JWT é composto da seguinte maneira:

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

A string de base da assinatura é a seguinte:

{Base64url encoded header}.{Base64url encoded claim set}
Como formar o cabeçalho JWT

O cabeçalho consiste em dois campos que indicam o algoritmo de assinatura e o formato da declaração. Ambos os campos são obrigatórios, e cada um tem apenas um valor. À medida que outros algoritmos e formatos são introduzidos, esse cabeçalho muda de acordo.

As contas de serviço dependem do algoritmo RSA SHA-256 e do formato de token JWT. Como resultado, a representação JSON do cabeçalho é a seguinte:

{"alg":"RS256","typ":"JWT"}

A representação Base64url disso é a seguinte:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Como formar o conjunto de declarações JWT

O conjunto de declarações JWT contém informações sobre o JWT, incluindo as permissões solicitadas (escopos), o destino do token, o emissor, a hora em que o token foi emitido e o ciclo de vida dele. A maioria dos campos é obrigatória. Assim como o cabeçalho JWT, o conjunto de declarações JWT é um objeto JSON e é usado no cálculo da assinatura.

Reivindicações obrigatórias

As reivindicações obrigatórias no conjunto de declarações JWT são mostradas abaixo. Elas podem aparecer em qualquer ordem no conjunto de reivindicações.

Nome Descrição
iss O endereço de e-mail da conta de serviço.
scope Uma lista delimitada por espaço das permissões solicitadas pelo aplicativo.
aud Um descritor do destino pretendido da declaração. Ao fazer uma solicitação de token de acesso, esse valor é sempre https://oauth2.googleapis.com/token.
exp O prazo de validade da declaração, especificado como segundos desde 00:00:00 UTC, 1o de janeiro de 1970. Esse valor tem um máximo de uma hora após o horário emitido.
iat A hora em que a declaração foi emitida, especificada em segundos desde 00:00:00 UTC, 1o de janeiro de 1970.

Veja a representação JSON dos campos obrigatórios em um conjunto de declarações JWT abaixo:

{
  "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
}
Outras reivindicações

Em alguns casos corporativos, um aplicativo pode usar a delegação em todo o domínio para agir em nome de um determinado usuário em uma organização. A permissão para esse tipo de falsificação de identidade precisa ser concedida antes que um aplicativo possa representar um usuário e geralmente é realizada por um superadministrador. Para mais informações, consulte Controlar o acesso à API com delegação em todo o domínio.

Para receber um token de acesso que concede a um aplicativo acesso delegado a um recurso, inclua o endereço de e-mail do usuário na declaração JWT definida como o valor do campo sub.

Nome Descrição
sub O endereço de e-mail do usuário para que o aplicativo está solicitando acesso delegado.

Se um aplicativo não tiver permissão para representar um usuário, a resposta a uma solicitação de token de acesso que incluir o campo sub será um erro.

Veja abaixo um exemplo de um conjunto de declarações JWT que inclui o 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
}
Como codificar o conjunto de declarações JWT

Assim como o cabeçalho JWT, o conjunto de declarações JWT precisa ser serializado para UTF-8 e codificado em Base64url. Veja abaixo um exemplo de uma representação JSON de um conjunto de declarações JWT:

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

A JSON Web Signature (JWS) é a especificação que orienta a mecânica de geração da assinatura do JWT. A entrada da assinatura é a matriz de bytes do seguinte conteúdo:

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

O algoritmo de assinatura no cabeçalho JWT precisa ser usado ao calcular a assinatura. O único algoritmo de assinatura compatível com o servidor de autorização do Google OAuth 2.0 é o RSA usando o algoritmo de hash SHA-256. Isso é expresso como RS256 no campo alg no cabeçalho JWT.

Assine a representação UTF-8 da entrada usando SHA256withRSA (também conhecido como RSASSA-PKCS1-V1_5-SIGN com a função hash SHA-256) com a chave privada recebida de Google API Console. A saída será uma matriz de bytes.

A assinatura precisa ter a codificação Base64url. O cabeçalho, o conjunto de declarações e a assinatura são concatenados com um caractere de ponto (.). O resultado é o JWT. Precisa ser o seguinte (quebras de linhas adicionadas para maior clareza):

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

Veja abaixo um exemplo de JWT antes da codificação 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]

Veja abaixo um exemplo de JWT assinado e pronto para transmissão:

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

Como fazer a solicitação do token de acesso

Depois de gerar o JWT assinado, um aplicativo pode usá-lo para solicitar um token de acesso. Essa solicitação de token de acesso é uma solicitação HTTPS POST e o corpo é codificado pelo URL. O URL é exibido abaixo:

https://oauth2.googleapis.com/token

Os seguintes parâmetros são obrigatórios na solicitação HTTPS POST:

Nome Descrição
grant_type Use a string a seguir, codificada por URL, conforme necessário: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion O JWT, incluindo a assinatura.

Veja abaixo um despejo bruto da solicitação HTTPS POST usada em uma solicitação de token de acesso:

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

Veja abaixo a mesma solicitação, usando 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

Como processar a resposta

Se o JWT e a solicitação do token de acesso estiverem devidamente formados e a conta de serviço tiver permissão para realizar a operação, a resposta JSON do servidor de autorização incluirá um token de acesso. Veja a seguir um exemplo de resposta:

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

Os tokens de acesso podem ser reutilizados durante a janela de duração especificada pelo valor expires_in.

Como chamar APIs do Google

Java

Use o objeto GoogleCredential para chamar as APIs do Google concluindo as seguintes etapas:

  1. Crie um objeto de serviço para a API que você quer chamar usando o objeto GoogleCredential. Por exemplo:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Faça solicitações ao serviço da API usando a interface fornecida pelo objeto de serviço. Por exemplo, para listar as instâncias de bancos de dados do Cloud SQL no projeto empolgante-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Use o objeto Credentials autorizado para chamar APIs do Google concluindo as seguintes etapas:

  1. Crie um objeto de serviço para a API que você quer chamar. Crie um objeto de serviço chamando a função build com o nome e a versão da API e o objeto Credentials autorizado. Por exemplo, para chamar a versão 1beta3 da API de administração do Cloud SQL:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Faça solicitações ao serviço da API usando a interface fornecida pelo objeto de serviço. Por exemplo, para listar as instâncias de bancos de dados do Cloud SQL no projeto empolgante-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Depois que seu aplicativo recebe um token de acesso, é possível usá-lo para fazer chamadas para uma API do Google em nome de uma determinada conta de serviço ou conta de usuário se o escopo de acesso exigido pela API tiver sido concedido. Para fazer isso, inclua o token de acesso em uma solicitação para a API incluindo um parâmetro de consulta access_token ou um valor Bearer de cabeçalho HTTP Authorization. Quando possível, o cabeçalho HTTP é preferível, porque as strings de consulta tendem a ser visíveis nos registros do servidor. Na maioria dos casos, você pode usar uma biblioteca de cliente para configurar as chamadas para APIs do Google, por exemplo, ao chamar a API Drive Files.

É possível testar todas as APIs do Google e ver os escopos delas no OAuth 2.0 Playground.

Exemplos de HTTP GET

Uma chamada para o endpoint drive.files (a API Drive Files) usando o cabeçalho HTTP Authorization: Bearer pode ser semelhante a esta. Você precisa especificar seu próprio token de acesso:

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

Esta é uma chamada para a mesma API para o usuário autenticado usando o parâmetro de string de consulta access_token:

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

Exemplos de curl

É possível testar esses comandos com o aplicativo de linha de comando curl. Veja um exemplo que usa a opção de cabeçalho HTTP (preferencial):

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

Ou, alternativamente, a opção de parâmetro da string de consulta:

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

Quando os tokens de acesso expiram

Os tokens de acesso emitidos pelo servidor de autorização do OAuth 2.0 do Google expiram após a duração fornecida pelo valor expires_in. Quando um token de acesso expira, o aplicativo precisa gerar outro JWT, assiná-lo e solicitar outro token de acesso.

Códigos de erro do JWT

Campo error Campo error_description Significado Como resolver
unauthorized_client Unauthorized client or scope in request. Se você estiver tentando usar a delegação em todo o domínio, a conta de serviço não está autorizada no Admin Console do domínio do usuário.

Verifique se a conta de serviço está autorizada na página Delegação em todo o domínio do Admin Console para o usuário na declaração sub (campo).

Embora geralmente leve alguns minutos, a autorização pode levar até 24 horas para ser propagada para todos os usuários na sua Conta do Google.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Uma conta de serviço foi autorizada usando o endereço de e-mail do cliente em vez do ID do cliente (numérico) no Admin Console. Na página Delegação em todo o domínio no Admin Console, remova o cliente e adicione-o novamente com o ID numérico.
access_denied (qualquer valor) Se você estiver usando a delegação em todo o domínio, um ou mais escopos solicitados não estão autorizados no Admin Console.

Verifique se a conta de serviço está autorizada na página Delegação em todo o domínio do Admin Console do usuário na declaração sub (campo) e se ela inclui todos os escopos solicitados na declaração scope do JWT.

Embora geralmente leve alguns minutos, a autorização pode levar até 24 horas para ser propagada para todos os usuários na sua Conta do Google.

admin_policy_enforced (qualquer valor) A Conta do Google não autoriza um ou mais escopos solicitados devido às políticas do administrador do Google Workspace.

Consulte o artigo de ajuda do administrador do Google Workspace Controlar quais apps internos e de terceiros acessam os dados do Google Workspace para mais informações sobre como um administrador pode restringir o acesso a todos os escopos ou aos escopos confidenciais e restritos até que o acesso seja explicitamente concedido ao ID do cliente OAuth.

invalid_client (qualquer valor)

O token OAuth ou cliente OAuth é inválido ou está configurado incorretamente.

Consulte a descrição do erro para mais detalhes.

Verifique se o token JWT é válido e contém declarações corretas.

Verifique se o cliente OAuth e a conta de serviço estão configurados corretamente e se você está usando o endereço de e-mail correto.

Verifique se o token JWT está correto e foi emitido para o ID do cliente na solicitação.

invalid_grant Not a valid email. O usuário não existe. Verifique se o endereço de e-mail na declaração (campo) sub está correto.
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.

Normalmente, isso significa que o horário local do sistema não está correto. Também pode acontecer se o valor exp for maior que 65 minutos no futuro a partir do valor iat ou se o valor exp for menor que iat.

Verifique se o relógio do sistema em que o JWT foi gerado está correto. Se necessário, sincronize seu horário com o Google NTP.

invalid_grant Invalid JWT Signature.

A declaração JWT é assinada com uma chave privada não associada à conta de serviço identificada pelo e-mail do cliente ou se a chave usada foi excluída, desativada ou expirou.

Como alternativa, a declaração JWT pode estar codificada incorretamente. Ela precisa ser codificada em Base64, sem novas linhas ou sinais de igual de padding.

Decodifique o conjunto de declarações JWT e verifique a chave que assinou a declaração está associada à conta de serviço.

Tente usar uma biblioteca OAuth fornecida pelo Google para garantir que o JWT seja gerado corretamente.

invalid_scope Invalid OAuth scope or ID token audience provided. Nenhum escopo foi solicitado (lista vazia de escopos) ou um dos escopos solicitados não existe (ou seja, é inválido).

Verifique se a declaração scope (campo) do JWT está preenchida e compare os escopos contidos nela com os escopos documentados para as APIs que você quer usar, para garantir que não haja erros ou erros de digitação.

A lista de escopos na declaração scope precisa ser separada por espaços, e não por vírgulas.

disabled_client The OAuth client was disabled. A chave usada para assinar a declaração do JWT está desativada.

Acesse Google API Consolee, em IAM e administrador > Contas de serviço, ative a conta de serviço que contém o "ID da chave" usado para assinar a declaração.

org_internal This client is restricted to users within its organization. O ID do cliente OAuth na solicitação faz parte de um projeto que limita o acesso a Contas do Google em uma organização específica do Google Cloud.

Use uma conta de serviço da organização para autenticar. Confirme a configuração do tipo de usuário para seu aplicativo OAuth.

Adendo: autorização da conta de serviço sem OAuth

Com algumas APIs do Google, é possível fazer chamadas de API autorizadas usando um JWT assinado diretamente como um token do portador, em vez de um token de acesso do OAuth 2.0. Quando isso é possível, evite fazer uma solicitação de rede ao servidor de autorização do Google antes de fazer uma chamada de API.

Se a API que você quer chamar tiver uma definição de serviço publicada no repositório do GitHub de APIs do Google, será possível fazer chamadas de API autorizadas usando um JWT em vez de um token de acesso. Basta seguir estas etapas:

  1. Crie uma conta de serviço conforme descrito acima. Mantenha o arquivo JSON recebido ao criar a conta.
  2. Usando qualquer biblioteca JWT padrão, como uma encontrada em jwt.io, crie um JWT com um cabeçalho e payload como no exemplo a seguir:
    {
      "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
    }
    • No campo kid do cabeçalho, especifique o ID da chave privada da conta de serviço. Esse valor está no campo private_key_id do arquivo JSON da conta de serviço.
    • Nos campos iss e sub, especifique o endereço de e-mail da sua conta de serviço. Esse valor está no campo client_email do arquivo JSON da conta de serviço.
    • No campo aud, especifique o endpoint da API. Por exemplo, https://SERVICE.googleapis.com/.
    • No campo iat, especifique a hora atual do Unix. Para o campo exp, especifique a hora exatamente 3.600 segundos depois, quando o JWT expira.

Assine o JWT com o RSA-256 usando a chave privada encontrada no arquivo JSON da sua conta de serviço.

Exemplo:

Java

Usando 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

Com o 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. Chame a API usando o JWT assinado como o token do portador:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com