将 OAuth 2.0 用于服务器到服务器应用程序

Google OAuth 2.0 系统支持服务器到服务器的交互,例如 Web 应用程序和 Google 服务之间的交互。对于这种情况,你需要一个服务帐户,这是属于你的应用程序,而不是对单个最终用户的账户。您的应用程序代表服务帐号调用 Google API,因此用户不会直接参与其中。这种情况有时称为“两条腿的 OAuth”或“2LO”。 (相关术语“三足 OAuth”是指您的应用程序代表最终用户调用 Google API 并且有时需要用户同意的场景。)

通常,当应用程序使用 Google API 处理自己的数据而不是用户的数据时,应用程序会使用服务帐户。例如,使用 Google Cloud Datastore 进行数据持久化的应用程序将使用服务帐户来验证其对 Google Cloud Datastore API 的调用。

谷歌工作区域管理员还可以授予服务帐户域范围内的授权访问用户数据代表域中的用户的。

本文档描述了应用程序如何使用 Google API 客户端库(推荐)或 HTTP 完成服务器到服务器 OAuth 2.0 流程。

概述

支持服务器到服务器交互,首先要建立在你的项目中的服务帐户 API Console。如果您想访问 Google Workspace 帐户中用户的用户数据,请将域范围的访问权限委托给服务帐户。

然后,您的应用程序准备进行授权 API 调用,方法是使用服务帐户的凭据从 OAuth 2.0 身份验证服务器请求访问令牌。

最后,您的应用程序可以使用访问令牌来调用 Google API。

创建服务帐号

服务帐户的凭据包括生成的唯一电子邮件地址和至少一个公钥/私钥对。如果启用了域范围委派,则客户端 ID 也是服务帐户凭据的一部分。

如果您的应用程序在 Google App Engine 上运行,则在您创建项目时会自动设置一个服务帐户。

如果您的应用程序在 Google Compute Engine 上运行,则在您创建项目时也会自动设置一个服务帐户,但您必须在创建 Google Compute Engine 实例时指定您的应用程序需要访问的范围。欲了解更多信息,请参阅准备一个实例来使用服务帐户

如果您的应用程序无法在谷歌应用程序引擎或谷歌计算引擎运行,必须获得在这些凭据 Google API Console。要生成服务帐户凭据,或查看您已生成的公共凭据,请执行以下操作:

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

  1. 打开 Service accounts page
  2. If prompted, select a project, or create a new one.
  3. 点击创建服务帐户
  4. 服务帐户的详细信息,键入一个名称,ID和服务帐户的描述,然后单击创建并继续
  5. 可选:在授予此服务帐户访问到项目中,选择IAM角色授予服务帐户。
  6. 点击继续
  7. 可选:在授予用户访问该服务帐户,添加允许使用和管理服务帐户的用户或组。
  8. 点击完成
  9. 点击创建键,然后单击创建

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

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

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

您可以返回到 API Console随时查看电子邮件地址,公钥指纹等信息,或产生额外的公共/私有密钥对。有关服务帐户凭据的详细信息 API Console,请参阅服务帐户在 API Console帮助文件。

记下服务帐户的电子邮件地址,并将服务帐户的私钥文件存储在您的应用程序可访问的位置。您的应用程序需要它们来进行授权的 API 调用。

将域范围的权限委派给服务帐户

如果您拥有 Google Workspace 帐户,则组织的管理员可以授权应用程序代表 Google Workspace 域中的用户访问用户数据。例如,使用 Google Calendar API 向 Google Workspace 域中所有用户的日历添加事件的应用程序将使用服务帐户代表用户访问 Google Calendar API。授权服务帐户代表域中的用户访问数据有时称为“将域范围的权限委托给服务帐户”。

要将域范围的权限委派给服务帐号,Google Workspace 域的超级管理员必须完成以下步骤:

  1. 从您的工作空间谷歌域的管理控制台,进入主菜单 >安全> API控制
  2. 域宽代表团窗格中,选择管理域范围的代表团
  3. 点击添加新的
  4. 客户ID字段中输入服务帐户的客户端ID。您可以找到您的服务帐户的客户ID Service accounts page
  5. OAuth范围(以逗号分隔)字段中输入范围的列表中,你的应用程序应该被授予访问权限。例如,如果你的应用需要域范围内的完全访问谷歌云端硬盘API和谷歌日历API,请输入:https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth /日历
  6. 点击授权

您的应用程序现在有权以您域中的用户身份进行 API 调用(以“模拟”用户)。当您准备进行授权的 API 调用时,您可以指定要模拟的用户。

准备进行授权的 API 调用

爪哇

当您获得来自客户的电子邮件地址和私有密钥 API Console,使用谷歌API客户端库为Java创建GoogleCredential从服务帐户的凭据对象和作用域您的应用程序需要访问。例如:

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

如果您正在开发在谷歌云平台的应用程序,你可以使用应用程序的默认凭证代替,这样可以简化过程。

委派全域权限

如果你已经委派域范围内的访问服务帐户,你要模拟用户帐户,指定与用户帐户的电子邮件地址createDelegated的方法GoogleCredential对象。例如:

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

使用GoogleCredential对象调用API的谷歌应用程序中。

Python

你获得来自客户的电子邮件地址和私钥后 API Console,使用谷歌API客户端库的Python完成以下步骤:

  1. 创建一个Credentials从服务帐户的凭据对象和作用域您的应用程序需要访问。例如:
    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)

    如果您正在开发在谷歌云平台的应用程序,你可以使用应用程序的默认凭证代替,这样可以简化过程。

  2. 委派全域权限

    如果你已经委派域范围内的访问服务帐户,你要模拟用户帐户,使用with_subject现有的方法ServiceAccountCredentials对象。例如:

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

使用 Credentials 对象在您的应用程序中调用 Google API。

HTTP/REST

你获得来自客户端ID和私钥后 API Console,你的应用程序需要完成以下步骤:

  1. 创建一个 JSON Web 令牌(JWT,发音为“jot”),其中包括标头、声明集和签名。
  2. 从 Google OAuth 2.0 授权服务器请求访问令牌。
  3. 处理授权服务器返回的 JSON 响应。

以下部分描述了如何完成这些步骤。

如果响应包括访问令牌,你可以使用令牌来访问调用API谷歌。 (如果响应不包含访问令牌,则您的 JWT 和令牌请求可能未正确形成,或者服务帐户可能无权访问请求的范围。)

当访问令牌过期,您的应用程序生成另一智威汤逊,签名,然后请求另一个访问令牌。

您的服务器应用程序使用 JWT 从 Google 授权服务器请求令牌,然后使用该令牌调用 Google API 端点。不涉及最终用户。

本节的其余部分描述了创建 JWT、签署 JWT、形成访问令牌请求和处理响应的细节。

创建 JWT

JWT 由三部分组成:标头、声明集和签名。标头和声明集是 JSON 对象。这些 JSON 对象被序列化为 UTF-8 字节,然后使用 Base64url 编码进行编码。由于重复的编码操作,这种编码提供了对编码变化的弹性。头,如权利要求集,和签名用句点(连接到一起. )字符。

JWT 的组成如下:

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

签名的基本字符串如下:

{Base64url encoded header}.{Base64url encoded claim set}
形成 JWT 标头

标头由两个字段组成,指示签名算法和断言的格式。这两个字段都是必填字段,每个字段只有一个值。随着其他算法和格式的引入,此标头将相应更改。

服务帐户依赖于 RSA SHA-256 算法和 JWT 令牌格式。因此,标头的 JSON 表示如下:

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

其 Base64url 表示如下:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
形成 JWT 声明集

JWT 声明集包含有关 JWT 的信息,包括请求的权限(范围)、令牌的目标、颁发者、颁发令牌的时间以及令牌的生命周期。大多数字段都是必填的。与 JWT 标头一样,JWT 声明集是一个 JSON 对象,用于计算签名。

所需声明

JWT 声明集中所需的声明如下所示。它们可能以任何顺序出现在声明集中。

姓名描述
iss服务帐号的电子邮件地址。
scope应用程序请求的权限的空格分隔列表。
aud断言的预期目标的描述符。做一个访问令牌请求当该值始终https://oauth2.googleapis.com/token
exp断言的到期时间,指定为自 1970 年 1 月 1 日 00:00:00 UTC 起的秒数。该值在发布时间后最长为 1 小时。
iat发出断言的时间,指定为自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数。

JWT 声明集中所需字段的 JSON 表示如下所示:

{
  "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
}
附加索赔

在某些企业情况下,应用程序可以使用域范围的委派代表组织中的特定用户进行操作。在应用程序可以模拟用户之前,必须授予执行此类模拟的权限,并且通常由超级管理员处理。欲了解更多信息,请参见与全域代表团控制API访问权限

为了获得令牌授权应用程序授权访问资源的访问,包括智威汤逊声明组作为价值的用户的电子邮件地址, sub场。

姓名描述
sub应用程序为其请求委派访问权限的用户的电子邮件地址。

如果应用程序没有权限模拟用户,响应于包括所述访问令牌请求sub字段将是一个误差

一个如权利要求JWT集包括所述的一个例子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
}
编码 JWT 声明集

与 JWT 标头一样,JWT 声明集应序列化为 UTF-8 和 Base64url 安全编码。以下是 JWT 声明集的 JSON 表示示例:

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

JSON网络签名(JWS)是规范,产生了智威汤逊签名的引导机制。签名的输入是以下内容的字节数组:

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

计算签名时必须使用 JWT 头中的签名算法。 Google OAuth 2.0 授权服务器支持的唯一签名算法是使用 SHA-256 散列算法的 RSA。这表现为RS256alg在JWT报头字段。

拍使用SHA256withRSA与从所获得的私钥的输入(也称为RSASSA-PKCS1-v1_5中-SIGN与SHA-256散列函数)的UTF-8表示 Google API Console。输出将是一个字节数组。

然后签名必须是 Base64url 编码的。头,如权利要求集,和签名用句点(连接到一起. )字符。结果是 JWT。它应该如下(为清楚起见添加了换行符):

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

下面是 Base64url 编码之前的 JWT 示例:

{"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]

下面是一个已签名并准备传输的 JWT 示例:

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

发出访问令牌请求

生成签名的 JWT 后,应用程序可以使用它来请求访问令牌。此访问令牌请求是HTTPS POST请求,和所述主体是URL编码。网址如下所示:

https://oauth2.googleapis.com/token

下列参数是必需的在HTTPS POST请求:

姓名描述
grant_type使用下面的字符串,URL编码为必要的: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JWT,包括签名。

下面是HTTPS的原始转储POST在令牌请求的接入请求使用:

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

下面是相同的请求,使用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

处理响应

如果 JWT 和访问令牌请求格式正确并且服务帐户有权执行该操作,则来自授权服务器的 JSON 响应包含访问令牌。以下是响应示例:

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

访问令牌可以由指定的持续时间窗口期间被重新使用expires_in值。

调用 Google API

爪哇

使用GoogleCredential对象通过完成以下步骤来调用谷歌的API:

  1. 创建您要使用调用API服务对象GoogleCredential对象。例如:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. 请使用请求API服务由服务对象提供的接口。例如,要列出Cloud SQL资料库的情况下,在令人兴奋的-例如-123项目:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

使用授权Credentials对象通过完成以下步骤来调用谷歌的API:

  1. 为您要调用的 API 构建一个服务对象。您可以通过调用建立AA服务对象build的名称和版本的API和授权功能Credentials对象。例如,要调用的Cloud SQL管理API的版本1beta3:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. 请使用请求API服务由服务对象提供的接口。例如,要列出Cloud SQL资料库的情况下,在令人兴奋的-例如-123项目:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

在您的应用程序获得访问令牌后,如果已授予 API 所需的访问范围,您可以使用该令牌代表给定的服务帐户或用户帐户调用 Google API。要做到这一点,包括通过包括一个在请求令牌给API访问access_token查询参数或Authorization HTTP标头Bearer值。如果可能,最好使用 HTTP 标头,因为查询字符串往往在服务器日志中可见。在大多数情况下,你可以使用客户端库建立到谷歌的API您的来电(例如,当调用驱动器文件API )。

你可以尝试所有的谷歌API和查看他们的范围在的OAuth 2.0游乐场

HTTP GET 示例

在调用drive.files使用端点(驱动文件API) Authorization: Bearer HTTP标头看起来像下面这样。请注意,您需要指定自己的访问令牌:

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

下面是使用经过验证的用户相同的API调用access_token查询字符串参数:

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

curl的例子

您可以测试与这些命令curl命令行应用程序。下面是一个使用 HTTP 标头选项(首选)的示例:

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

或者,查询字符串参数选项:

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

访问令牌何时到期

访问令牌由谷歌的OAuth 2.0授权服务器颁发的规定期限到期后expires_in值。当访问令牌过期时,应用程序应生成另一个 JWT,对其进行签名并请求另一个访问令牌。

JWT 错误代码

errorerror_description意义如何解决
unauthorized_client Unauthorized client or scope in request.如果您尝试使用域范围委派,则该服务帐户未在用户域的管理控制台中获得授权。

确保服务帐户被授权在域范围内的代表团为在用户管理控制台的页sub要求(场)。

虽然通常需要几分钟时间,但最长可能需要 24 小时才能将授权传播给您 Google 帐户中的所有用户。

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.使用客户端电子邮件地址而非管理控制台中的客户端 ID(数字)对服务帐号进行了授权。域范围内的代表团在管理控制台页面,删除客户端,并与数字ID重新添加它。
access_denied (任何值)如果您使用域范围委派,则在管理控制台中未授权一个或多个请求的范围。

确保服务帐户被授权在域范围内的代表团为在用户管理控制台的页sub要求(场),而且它包括所有的作用域你请求的scope的JWT的要求。

虽然通常需要几分钟时间,但最长可能需要 24 小时才能将授权传播给您 Google 帐户中的所有用户。

invalid_grant Not a valid email.该用户不存在。检查中的电子邮件地址sub要求(场)是正确的。
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.

通常,这意味着本地系统时间不正确。如果它也可能发生exp值是从在未来超过65分钟iat值,或exp值低于iat值。

确保生成 JWT 的系统上的时钟正确。如果有必要,同步你的时间谷歌NTP

invalid_grant Invalid JWT Signature.

JWT 断言使用与客户端电子邮件标识的服务帐户无关的私钥进行签名,或者使用的密钥已被删除、禁用或已过期。

或者,JWT 断言可能编码不正确 - 它必须是 Base64 编码的,没有换行符或填充等号。

解码 JWT 声明集并验证签署断言的密钥与服务帐户相关联。

尝试使用 Google 提供的 OAuth 库来确保正确生成 JWT。

invalid_scope Invalid OAuth scope or ID token audience provided.未请求任何范围(空的范围列表),或请求的范围之一不存在(即无效)。

确保scope的JWT的要求(场)填充,并比较范围,它包含您要使用API的文件范围,以确保没有错误或错别字。

注意,在范围列表scope要求需要用空格隔开,而不是逗号。

disabled_client The OAuth client was disabled.用于签署 JWT 断言的密钥已禁用。

转至 Google API ConsoleIAM与管理>服务帐户下,使其中包含用于签署断言“钥匙ID”的服务帐户。

附录:无需 OAuth 的服务帐户授权

借助某些 Google API,您可以使用已签名的 JWT 直接作为不记名令牌(而不是 OAuth 2.0 访问令牌)进行授权 API 调用。如果可能,您可以避免在进行 API 调用之前向 Google 的授权服务器发出网络请求。

如果你想调用API具有公布在服务定义谷歌的API库GitHub的,你可以使用一个智威汤逊,而不是一个访问令牌做出授权API调用。这样做:

  1. 创建服务帐户如上所述。请务必保留创建帐户时获得的 JSON 文件。
  2. 使用任何标准JWT库,诸如一个在发现jwt.io ,创建具有首部和有效载荷一样以下示例的JWT:
    {
      "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
    }
    • 对于kid在头字段中,指定服务帐户的私有密钥ID。你可以找到在这个值private_key_id您的服务帐户JSON文件的领域。
    • 对于isssub域,指定服务帐户的电子邮件地址。你可以找到在这个值client_email您的服务帐户JSON文件的领域。
    • 对于aud字段中指定的API端点。例如: https:// SERVICE .googleapis.com/
    • 对于iat字段中,指定当前Unix的时间,而对于exp字段,正是3600秒后,指定时间时,智威汤逊将到期。

使用在您的服务帐户 JSON 文件中找到的私钥,通过 RSA-256 对 JWT 进行签名。

例如:

爪哇

使用谷歌的API的Java客户端Java的智威汤逊

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

使用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. 调用API,使用签名的JWT作为承载令牌:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com