Usar o OAuth 2.0 para aplicativos de servidor para servidor

O sistema do Google OAuth 2.0 aceita interações de servidor para servidor, como as que ocorrem entre um aplicativo da Web e um serviço do Google. Para esse cenário, você precisa de uma conta de serviço, que pertence ao aplicativo em vez de um usuário final individual. O aplicativo chama as APIs do Google em nome da conta de serviço. Assim, os usuários não são diretamente envolvidos. Esse cenário às vezes é chamado de "OAuth de duas pernas" ou "2LO". O termo relacionado "OAuth de três pernas" se refere a cenários em que o aplicativo chama as APIs do Google em nome dos usuários finais e em que o consentimento do usuário às vezes é necessário.

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

Os administradores de domínio do Google Workspace também podem conceder autoridade em todo o domínio a contas de serviço para acessar dados de usuários em nome deles.

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

Visão geral

Para oferecer suporte às interações de servidor para servidor, primeiro crie uma conta de serviço para seu projeto no API Console. Se você quiser acessar os dados dos usuários na sua 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.

Se o aplicativo for executado no Google App Engine, uma conta de serviço será configurada automaticamente quando você criar o projeto.

Se o aplicativo for executado no Google Compute Engine, uma conta de serviço também será configurada automaticamente ao criar o projeto, mas você precisará especificar os escopos a que o aplicativo precisa ter acesso ao criar uma instância do Google Compute Engine. Para mais informações, consulte 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, será necessário conseguir essas credenciais no Google API Console. Para gerar credenciais de conta de serviço ou conferir as credenciais públicas que você já gerou, faça o seguinte:

首先,创建一个服务帐户:

  1. 打开 Service accounts page
  2. If prompted, select a project, or create a new one.
  3. 单击创建服务帐户
  4. Service account details下,键入服务帐户的名称、ID 和描述,然后点击Create and continue
  5. 可选:在Grant this service account access to project下,选择要授予服务帐户的 IAM 角色。
  6. 单击继续
  7. 可选:在Grant users access to this service account下,添加允许使用和管理服务帐户的用户或组。
  8. 单击完成

接下来,创建一个服务帐户密钥:

  1. 单击您创建的服务帐户的电子邮件地址。
  2. 单击密钥选项卡。
  3. 添加密钥下拉列表中,选择创建新密钥
  4. 单击创建

您的新公钥/私钥对已生成并下载到您的机器上;它作为私钥的唯一副本。您有责任安全地存储它。如果您丢失了这个密钥对,您将需要生成一个新的。

Você pode retornar ao API Console a qualquer momento para conferir o endereço de e-mail, as impressões digitais de chave pública e outras informações ou para 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 de chave privada dela em um local acessível ao seu app. O aplicativo precisa deles para fazer chamadas de API autorizadas.

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

Usando uma conta do Google Workspace, um administrador do Workspace na organização pode autorizar um aplicativo a acessar dados de usuários do Workspace em nome dos 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 usa 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 em 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 Menu principal > Segurança > Controle de dados e acesso > 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 Adicionar novo.
  4. No campo ID do cliente, digite o ID do cliente da conta de serviço. Você pode encontrar o ID do cliente da sua conta de serviço no Service accounts page.
  5. No campo Escopos do OAuth (separados por vírgulas), insira a lista de escopos a que o aplicativo pode ter acesso. Por exemplo, se o app precisar de acesso total em todo o domínio à API Google Drive e à API Google Calendar, insira: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Clique em Autorizar.

Agora, seu aplicativo tem autoridade para fazer chamadas de API como usuários no seu domínio do Workspace para "imitar" usuários. Ao se preparar para fazer essas chamadas de API delegadas, você especifica explicitamente o usuário a ser imitado.

Como se preparar para fazer uma chamada de API delegada

Java

Depois de receber o endereço de e-mail do cliente e a chave privada do API Console, use a Biblioteca de cliente das APIs do Google para Java para criar um objeto GoogleCredential com base nas credenciais da conta de serviço e nos escopos que o aplicativo precisa acessar. 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 app no Google Cloud Platform, use as credenciais padrão do aplicativo para simplificar o processo.

Delegar autoridade em todo o domínio

Se você tiver acesso delegado em todo o domínio à conta de serviço e quiser falsificar a identidade de 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("workspace-user@example.com");

O código acima usa o objeto GoogleCredential para chamar o método createDelegated(). O argumento do método createDelegated() precisa ser um usuário que pertence à sua conta do Workspace. O código que faz a solicitação vai usar essa credencial para chamar as APIs do Google com sua conta de serviço.

Python

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

  1. Crie um objeto Credentials com base nas credenciais da conta de serviço e nos escopos que o aplicativo precisa acessar. 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 app no Google Cloud Platform, use as credenciais padrão do aplicativo para simplificar o processo.

  2. Delegar autoridade em todo o domínio

    Se você tiver acesso delegado 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 app.

HTTP/REST

Depois de receber o ID do cliente e a chave privada do API Console, o aplicativo precisa concluir as seguintes etapas:

  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 do servidor de autorização do Google OAuth 2.0.
  3. Processe 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, você poderá usá-lo para chamar uma API do Google. Se a resposta não incluir um token de acesso, o JWT e a solicitação de token podem não estar formatados corretamente ou a conta de serviço pode não ter 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 as especificidades de criação, assinatura, formação da solicitação de token de acesso e tratamento da resposta.

Como criar um JWT

Um JWT é composto de 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 para bytes UTF-8 e, em seguida, codificados usando a codificação Base64url. Essa codificação oferece resiliência contra 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 forma:

{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 três campos que indicam o algoritmo de assinatura, o formato da declaração e o [ID da chave da conta de serviço](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) usado para assinar o JWT. O algoritmo e o formato são obrigatórios, e cada campo tem apenas um valor. À medida que mais algoritmos e formatos forem introduzidos, esse cabeçalho vai mudar de acordo. O ID da chave é opcional, e se um ID incorreto for especificado, o GCP tentará usar todas as chaves associadas à conta de serviço para verificar o token e rejeitá-lo se nenhuma chave válida for encontrada. O Google se reserva o direito de rejeitar tokens com IDs de chave incorretos no futuro.

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", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

A representação Base64url é a seguinte:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
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 que estão sendo solicitadas (escopos), o destino do token, o emissor, o horário 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 declaraçõ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 tempo de expiração da declaração, especificado como segundos desde 00:00:00 UTC, 1º de janeiro de 1970. Esse valor tem um máximo de 1 hora após a emissão.
iat O horário em que a declaração foi emitida, especificado como segundos desde 00:00:00 UTC, 1º de janeiro de 1970.

Confira abaixo a representação JSON dos campos obrigatórios em um conjunto de declarações 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
}
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 usuário específico em uma organização. A permissão para realizar esse tipo de falsificação de identidade precisa ser concedida antes que um aplicativo possa falsificar um usuário e geralmente é processada por um superadministrador. Para mais informações, consulte Controlar o acesso da API com a delegação em todo o domínio.

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

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

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

Confira abaixo um exemplo de 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 codificação UTF-8 e codificação Base64url. Confira abaixo um exemplo de 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 assinatura JSON Web (JWS) é a especificação que orienta a mecânica de geração da assinatura para o 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 aceito pelo servidor de autorização OAuth 2.0 do Google é o RSA usando o algoritmo de hash SHA-256. Ele é 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 obtida de Google API Console. A saída será uma matriz de bytes.

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

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

Confira 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]

Confira 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 de 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 POST HTTPS, e o corpo é codificado em URL. O URL é mostrado abaixo:

https://oauth2.googleapis.com/token

Os seguintes parâmetros são necessários na solicitação POST HTTPS:

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

Confira abaixo um dump bruto da solicitação POST HTTPS 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

Confira 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 de token de acesso forem formados corretamente e a conta de serviço tiver permissão para realizar a operação, a resposta JSON do servidor de autorização vai 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 o período especificado pelo valor expires_in.

Como chamar APIs do Google

Java

Use o objeto GoogleCredential para chamar as APIs do Google seguindo estas etapas:

  1. Crie um objeto de serviço para a API que você quer chamar usando o objeto GoogleCredential. 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 exciting-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Use o objeto Credentials autorizado para chamar as APIs do Google seguindo estas etapas:

  1. Crie um objeto de serviço para a API que você quer chamar. Você cria 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 Cloud SQL Admin:
    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 exciting-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Depois que o aplicativo receber um token de acesso, ele poderá ser usado para fazer chamadas para uma API do Google em nome de uma determinada conta de serviço ou de usuário, se os escopos de acesso exigidos pela API tiverem sido concedidos. 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 ficar visíveis nos registros do servidor. Na maioria dos casos, é possível usar uma biblioteca de cliente para configurar suas chamadas para as APIs do Google. Por exemplo, ao chamar a API Drive Files.

Teste todas as APIs do Google e confira os escopos delas no OAuth 2.0 Playground.

Exemplos de GET HTTP

Uma chamada para o endpoint drive.files (a API Drive Files) usando o cabeçalho HTTP Authorization: Bearer pode ser semelhante ao seguinte. É necessário 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 do 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. Confira 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, como alternativa, a opção de parâmetro de 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 Google OAuth 2.0 expiram após o período fornecido pelo valor expires_in. Quando um token de acesso expirar, o aplicativo precisará gerar outro JWT, assiná-lo e solicitar outro token de acesso.

Códigos de erro 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 reivindicação sub (campo).

Embora geralmente demore alguns minutos, a autorização pode levar até 24 horas para ser aplicada a 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 do Admin Console, remova o cliente e adicione 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 serã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 para o usuário na declaração sub (campo) e se ela inclui todos os escopos que você está solicitando na declaração scope do JWT.

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

admin_policy_enforced (qualquer valor) A Conta do Google não consegue autorizar 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 escopos sensíveis e restritos até que o acesso seja concedido explicitamente ao seu ID do cliente OAuth.

invalid_client (qualquer valor)

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

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

Verifique se o token do JWT é válido e contém as 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 no campo (declaração) 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.

Geralmente, isso significa que o horário do sistema local não está correto. Isso também pode acontecer se o valor de exp for mais de 65 minutos no futuro em relação ao valor de iat ou se o valor de exp for menor que o valor de iat.

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

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 a chave que foi usada foi excluída, desativada ou expirou.

Como alternativa, a declaração JWT pode estar codificada incorretamente. Ela precisa ser codificada em base64, sem quebras de linha ou preenchimento de sinais iguais.

Decodificar o conjunto de declarações do JWT e verificar se 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 de escopos vazia) ou um dos escopos solicitados não existe (ou seja, é inválido).

Verifique se a declaração (campo) scope do JWT está preenchida e compare os escopos que ela contém com os escopos documentados das 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, não por vírgulas.

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

Acesse o 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 do Google Cloud específica.

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

Apêndice: autorização de 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 OAuth 2.0. Quando isso for possível, você não precisará fazer uma solicitação de rede para o 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 de APIs do Google no GitHub, será possível fazer chamadas de API autorizadas usando um JWT em vez de um token de acesso. Para fazer isso, siga 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 a encontrada em jwt.io, crie um JWT com um cabeçalho e um payload, como no exemplo abaixo:
    {
      "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 sua conta de serviço. Esse valor pode ser encontrado no campo private_key_id do arquivo JSON da sua conta de serviço.
    • Nos campos iss e sub, especifique o endereço de e-mail da sua conta de serviço. Esse valor pode ser encontrado no campo client_email do arquivo JSON da sua conta de serviço.
    • Para o campo aud, especifique o endpoint da API. Por exemplo, https://SERVICE.googleapis.com/.
    • Para o campo iat, especifique o horário atual do Unix e, para o campo exp, especifique o horário exatamente 3600 segundos depois, quando o JWT expirar.

Assine o JWT com RSA-256 usando a chave privada encontrada no arquivo JSON da 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

Usando 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 de portador:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

Como implementar a Proteção entre contas

Outra medida que você pode tomar para proteger as contas dos usuários é implementar a proteção entre contas usando o serviço de proteção entre contas do Google. Esse serviço permite que você se inscreva em notificações de eventos de segurança que fornecem informações ao seu app sobre mudanças importantes na conta do usuário. Em seguida, você pode usar as informações para tomar medidas dependendo de como você decide responder aos eventos.

Confira alguns exemplos de tipos de eventos enviados ao seu app pelo serviço de proteção entre contas do 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

Consulte a página Proteger contas de usuários com a Proteção entre contas para mais informações sobre como implementar a Proteção entre contas e a lista completa de eventos disponíveis.