Google Auth 库使用入门

Google Auth 库是适用于 Java 的开源身份验证客户端库。本文档介绍了如何使用此库对 Java 应用进行身份验证,以访问 Google Cloud 服务。

按照本指南操作,您将了解如何:

  • 使用 Maven、Gradle 或 Simple Build Tool (SBT) 将必要的身份验证库依赖项添加到您的项目中。
  • 使用各种方法进行身份验证,重点介绍应用默认凭据 (ADC)。
  • 配置高级身份验证方案,包括 Workload Identity 联合、员工身份联合和服务账号模拟。
  • 生成和使用降级令牌来限制权限。
  • 将凭据与 Google HTTP 客户端库集成。

本文档面向 Java 开发者。如需了解完整的 API 详情,请参阅 Google Auth 库 API 文档

适用于 Java 的 Google Auth 库包含以下 4 个制品:

  • google-auth-library-credentials 包含 Google 凭据的基类和接口。
  • google-auth-library-appengine 包含 App Engine 凭据,并依赖于 App Engine SDK。
  • google-auth-library-oauth2-http 包含各种凭据和实用方法,包括获取应用默认凭据的功能。它还提供了用于生成范围受限令牌的服务器端方法。
  • google-auth-library-cab-token-generator 提供了一种在客户端生成缩小权限范围的令牌的方法。

验证凭证配置

使用外部来源的凭证配置(例如 JSON、文件路径或数据流)时,您必须验证这些配置。向 Google API 或客户端库提供未经验证的凭据以进行身份验证,可能会损害系统和数据的安全性。Google Cloud

如需了解详情,请参阅外部来源凭证。 默认凭据。

导入身份验证库

如需导入身份验证库,请使用 com.google.cloud:libraries-bom 或将 Google Auth 库的物料清单与 Maven 或 Gradle 搭配使用。

Java SDK 库 - bom

如需使用身份验证库对 Java SDK 中的客户端库(例如 google-cloud-datastore)进行身份验证,请使用 libraries-bom,该依赖项会拉取与相应客户端库兼容的身份验证库版本。

例如,如需使用 pom.xml 通过 Maven 导入身份验证库,请执行以下操作:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.53.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

如果您不使用 libraries-bom 或其他客户端库,请使用 Google 身份验证库 BOM 直接导入身份验证模块。

Google Auth 库物料清单

您可以使用 Google 身份验证库物料清单来确保身份验证模块和相关的传递依赖项兼容。

Maven

请将以下内容添加到 pom.xml 文件:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.auth</groupId>
      <artifactId>google-auth-library-bom</artifactId>
      <version>1.30.1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies> 部分中,您可以指定所需的任何身份验证模块。例如,如需添加 google-auth-library-oauth2-http 模块,请添加以下 <dependency> 项:

<dependency>
  <groupId>com.google.auth</groupId>
  <!-- Let the BOM manage the module and dependency versions -->
  <!-- Replace with the module(s) that are needed -->
  <artifactId>google-auth-library-oauth2-http</artifactId>
</dependency>

将示例中的 google-auth-library-oauth2-http 替换为 google-auth-library-credentialsgoogle-auth-library-appengine,具体取决于您的应用需求。

Gradle

与 Maven 类似,Gradle 用户可以使用 google-auth-library-bom 来管理依赖项版本,并确保不同 google-auth-library 模块之间的兼容性。

如需将 BOM 与 Gradle 搭配使用,请将 BOM 添加为 platform 依赖项。然后,添加所需的 google-auth-library 模块。BOM 可确保您使用的所有模块的版本都兼容。例如,将以下内容添加到 build.gradle 文件中:

dependencies {
    // The BOM will manage the module versions and transitive dependencies
    implementation platform('com.google.auth:google-auth-library-bom:1.30.1')
    // Replace with the module(s) that are needed
    implementation 'com.google.auth:google-auth-library-oauth2-http'
}

Scala

与 Maven 和 Gradle 不同,SBT (Scala Build Tool) 不支持 Maven 物料清单 (BOM)。因此,在使用 Scala 时,您无法导入 google-auth-library-bom 来自动处理身份验证库模块及其传递依赖项的兼容版本。

您需要改为直接将每个必需的子模块添加到 build.sbt 文件中。请务必明确指定并统一所用所有 google-auth-library 模块的版本。未能保持版本一致可能会导致传递性依赖项之间出现版本冲突,从而可能导致应用中出现意外行为或运行时错误。

如果您使用的是 SBT,请将以下内容添加到您的依赖项中:

// Replace this with the implementation module that suits your needs
libraryDependencies += "com.google.auth" % "google-auth-library-oauth2-http" % "1.30.1"

GoogleCredential 迁移到 GoogleCredentials

来自 google-api-java-clientGoogleCredential 已弃用,建议改用 GoogleCredentials

使用应用默认凭据 (ADC) 实例化 GoogleCredentials。 建议采用以下方法:

GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();

GoogleCredentials 的使用方式取决于客户端库:

应用默认凭证

Google Auth 库为 Java 提供应用默认凭据 (ADC) 的实现。ADC 提供了一种获取授权凭据以调用 Google API 的方法。

如果您的应用需要与用户无关的一致身份和授权级别,请使用 ADC。我们建议使用 ADC 来授权对 Cloud API 的调用,尤其是在 Google Cloud上构建应用时。

ADC 还支持工作负载身份联合,使应用能够从 Amazon Web Services (AWS)、Microsoft Azure 或支持 OpenID Connect (OIDC) 的任何身份提供方等外部平台访问 Google Cloud 资源。对于非Google Cloud 环境,我们建议使用工作负载身份联合,因为这样就无需在本地下载、管理和存储服务账号私钥。

获取应用默认凭据

如需获取应用默认凭据,请使用 GoogleCredentials.getApplicationDefault()GoogleCredentials.getApplicationDefault(HttpTransportFactory)。这些方法会返回应用默认凭据,以标识和授权整个应用。

系统会按以下顺序搜索应用默认凭据:

  1. GOOGLE_APPLICATION_CREDENTIALS 环境变量指向的凭据文件。
  2. Google Cloud SDK gcloud auth application-default login 命令提供的凭据。
  3. Google App Engine 内置凭据。
  4. Google Cloud Shell 内置凭据。
  5. Google Compute Engine 内置凭据。
    • 您可以通过设置环境变量 NO_GCE_CHECK=true 来跳过此检查。
    • 通过设置环境变量 GCE_METADATA_HOST=<hostname> 自定义元数据服务器地址。

显式凭据加载

如需从服务账号 JSON 密钥获取凭据,请使用 GoogleCredentials.fromStream(InputStream)GoogleCredentials.fromStream(InputStream, HttpTransportFactory),如以下示例代码所示。

必须先刷新凭据,然后才能获取访问令牌。

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("/path/to/credentials.json"));
credentials.refreshIfExpired();
AccessToken token = credentials.getAccessToken();
// OR
AccessToken token = credentials.refreshAccessToken();

冒用的凭据

使用 ImpersonatedCredentials 允许凭据(主账号)模拟服务账号(目标账号)。这样,委托人就可以像目标一样访问资源,而无需目标的私钥。

如要使用 ImpersonatedCredentials,您必须满足以下要求:

  • 主账号的项目必须启用 IAMCredentials API。
  • 相应的主账号必须具有目标服务账号的 Service Account Token Creator (Identity and Access Management) 角色。

以下代码示例会创建 ImpersonatedCredentials。主账号的凭据是从应用默认凭据 (ADC) 中获取的。然后,使用生成的 ImpersonatedCredentials 以目标服务账号身份访问 Google Cloud Storage。

// The principal (ADC) has the Service Account Token Creator role on the target service account.
GoogleCredentials sourceCredentials =
    GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList("https://www.googleapis.com/auth/iam"));

ImpersonatedCredentials credentials =
    ImpersonatedCredentials.newBuilder()
        .setSourceCredentials(sourceCredentials)
        .setTargetPrincipal(
            "impersonated-account@project.iam.gserviceaccount.com")
        .setScopes(Arrays.asList("https://www.googleapis.com/auth/devstorage.read_only"))
        .build();

Storage storage =
    StorageOptions.newBuilder().setProjectId("project-id").setCredentials(credentials).build()
        .getService();

for (Bucket b : storage.list().iterateAll()) {
  System.out.println(b);
}

工作负载身份联合

借助工作负载身份联合,您的应用可以从 Amazon Web Services (AWS)、Microsoft Azure 或支持 OpenID Connect (OIDC) 的任何身份提供方访问 Google Cloud资源。

按照惯例,在 Google Cloud 外部运行的应用一直使用服务账号密钥来访问 Google Cloud 资源。通过使用身份联合,您的工作负载可以模拟服务账号。这样一来,外部工作负载便可以直接访问 Google Cloud 资源,从而消除与服务账号密钥相关的维护和安全负担。

从 AWS 访问资源

如需从 Amazon Web Services (AWS) 访问 Google Cloud 资源,您必须先配置工作负载身份联合。设置过程详见从 AWS 访问资源

在此过程中,您将生成凭据配置文件。此文件包含非敏感元数据,用于指示库如何检索外部主题令牌并将其交换为服务账号访问令牌。您可以使用 Google Cloud CLI 生成该文件:

# Generate an AWS configuration file.
gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>AWS_PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --aws \
    --output-file /path/to/generated/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • AWS_PROVIDER_ID:AWS 提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。

此示例会在指定的输出文件中生成配置文件。

如果您使用的是 AWS IMDSv2,则需要向 gcloud iam workload-identity-pools create-cred-config 命令添加一个额外的标志 --enable-imdsv2

gcloud iam workload-identity-pools create-cred-config \
    projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/AWS_PROVIDER_ID \
    --service-account SERVICE_ACCOUNT_EMAIL \
    --aws \
    --output-file /path/to/generated/config.json \
    --enable-imdsv2

您现在可以使用 Auth 库从 AWS 调用Google Cloud 资源。

从 Microsoft Azure 访问资源

如需从 Microsoft Azure 访问 Google Cloud 资源,您必须先配置工作负载身份联合。设置过程详见从 Azure 访问资源

在此过程中,您将生成凭据配置文件。此文件包含非敏感元数据,用于指示库如何检索外部主题令牌并将其交换为服务账号访问令牌。您可以使用 Google Cloud CLI 生成该文件:

# Generate an Azure configuration file.
gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>AZURE_PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --azure \
    --output-file /path/to/generated/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • AZURE_PROVIDER_ID:Azure 提供商 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。

此命令会在指定的输出文件中生成配置文件。

您现在可以使用 Auth 库从 Azure 调用 Google Cloud资源。

从 OIDC 身份提供商访问资源

如需从支持 OpenID Connect (OIDC) 的身份提供商访问 Google Cloud 资源,您必须先配置工作负载身份联合,具体操作请参阅从 OIDC 身份提供商配置工作负载身份联合

在此过程中,您将使用 Google Cloud CLI 生成凭据配置文件。此文件包含非敏感元数据,用于指示库如何检索外部正文令牌并将其交换为服务账号访问令牌。

对于 OIDC 提供方,身份验证库可以从本地文件(文件来源凭据)、本地服务器(网址来源凭据)或 X.509 证书和私钥组合(X.509 证书来源凭据)检索 OIDC 令牌。

文件溯源凭据

对于文件来源凭据,后台进程必须在到期前使用新的 OIDC 令牌不断刷新文件位置。对于有效期为 1 小时的令牌,您需要每小时更新文件中的令牌。您可以直接以纯文本或 JSON 格式存储令牌。

如需生成文件溯源 OIDC 配置,请运行以下命令:

# Generate an OIDC configuration file for file-sourced credentials.
gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>OIDC_PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --credential-source-file <var>PATH_TO_OIDC_ID_TOKEN</var> \
    # Optional arguments for file types. Default is "text":
    # --credential-source-type "json" \
    # Optional argument for the field that contains the OIDC credential.
    # This is required for json.
    # --credential-source-field-name "id_token" \
    --output-file /path/to/generated/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • OIDC_PROVIDER_ID:OIDC 提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。
  • PATH_TO_OIDC_ID_TOKEN:用于检索 OIDC 令牌的路径。

此命令会在指定的输出文件中生成配置文件。

网址溯源凭据

对于网址来源的凭据,本地服务器必须托管一个 GET 端点,该端点以纯文本或 JSON 格式提供 OIDC 令牌。您可以指定要在令牌请求中发送的其他 HTTP 标头(如果端点需要)。

如需生成网址来源的 OIDC 工作负载身份配置,请运行以下命令:

# Generate an OIDC configuration file for URL-sourced credentials.
gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>OIDC_PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --credential-source-url <var>URL_TO_GET_OIDC_TOKEN</var> \
    --credential-source-headers <var>HEADER_KEY=HEADER_VALUE</var> \
    # Optional arguments for file types. Default is "text":
    # --credential-source-type "json" \
    # Optional argument for the field that contains the OIDC credential.
    # This is required for json.
    # --credential-source-field-name "id_token" \
    --output-file /path/to/generated/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • OIDC_PROVIDER_ID:OIDC 提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。
  • URL_TO_GET_OIDC_TOKEN:要调用以检索 OIDC 令牌的本地服务器端点的网址。
  • HEADER_KEYHEADER_VALUE:要随 GET 请求传递给 URL_TO_GET_OIDC_TOKEN 的其他标头键值对,例如 Metadata-Flavor=Google

您现在可以使用 Auth 库从 OIDC 提供方调用Google Cloud 资源。

使用 X.509 证书来源的凭据访问资源

对于 X.509 证书来源的凭据,身份验证库会使用 X.509 证书和私钥来证明应用的身份。X.509 证书包含失效日期,必须在失效之前续订,才能保持访问权限。

如需了解详情,请参阅官方文档

为 X.509 联合生成配置文件

如需配置 X.509 证书来源的凭据,您需要生成两个单独的文件:主凭据配置文件和证书配置文件。

  • 主凭据配置文件包含身份验证所需的元数据。此文件还会引用证书配置文件。
  • 证书配置文件指定了 X.509 证书、私钥和信任链的文件路径。

gcloud iam workload-identity-pools create-cred-config 命令可用于创建这两种连接。

gcloud 创建证书配置文件的位置取决于您是否使用 --credential-cert-configuration-output-file 标志。

如果您省略 --credential-cert-configuration-output-file 标志,gcloud 会在身份验证库可以自动发现的默认已知位置创建证书配置文件。此方法适用于大多数使用情形。默认凭据配置文件名为 config.json,默认证书配置文件名为 certificate_config.json

例如,运行以下命令可使用默认行为创建配置文件:

gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --credential-cert-path "<var>PATH_TO_CERTIFICATE</var>" \
    --credential-cert-private-key-path "<var>PATH_TO_PRIVATE_KEY</var>" \
    --credential-cert-trust-chain-path "<var>PATH_TO_TRUST_CHAIN</var>" \
    --output-file /path/to/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • PROVIDER_ID:提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。
  • PATH_TO_CERTIFICATE:叶 X.509 证书所在的路径。
  • PATH_TO_PRIVATE_KEY:叶证书的相应私钥所在的路径。
  • PATH_TO_TRUST_CHAIN:X.509 证书信任链文件的路径。此文件应为 PEM 格式的文件,其中包含完成叶证书与工作负载身份联合池中配置的信任库之间的信任链所需的任何中间证书。此文件中的叶证书是可选的。

此命令会产生以下结果:

  • /path/to/config.json:在您指定的路径中创建。此文件将包含 "use_default_certificate_config": true,以指示客户端在默认路径中查找证书配置。
  • certificate_config.json:在默认 Google Cloud CLI 配置路径中创建,该路径通常为 Linux 和 macOS 上的 ~/.config/gcloud/certificate_config.json 或 Windows 上的 %APPDATA%\gcloud\certificate_config.json

自定义位置行为

如果您需要将证书配置文件存储在非默认位置,请使用 --credential-cert-configuration-output-file 标志。

示例命令(自定义位置):

gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>PROVIDER_ID</var> \
    --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
    --credential-cert-path "<var>PATH_TO_CERTIFICATE</var>" \
    --credential-cert-private-key-path "<var>PATH_TO_PRIVATE_KEY</var>" \
    --credential-cert-trust-chain-path "<var>PATH_TO_TRUST_CHAIN</var>" \
    --credential-cert-configuration-output-file "/custom/path/cert_config.json" \
    --output-file /path/to/config.json

此命令会产生以下结果:

  • /path/to/config.json:在您指定的路径中创建。此文件将包含指向自定义路径的 "certificate_config_location" 字段。
  • cert_config.json:在 /custom/path/cert_config.json 创建,如标志所指定。

您现在可以使用 Auth 库来调用具有 X.509 证书来源凭据的Google Cloud 资源。

将可执行文件溯源凭据与 OIDC 和 SAML 搭配使用

对于可执行文件来源的凭据,系统会使用本地可执行文件来检索第三方令牌。可执行文件必须以 JSON 格式将有效的未过期 OIDC ID 令牌或 SAML 断言提供给 stdout

如需使用可执行文件溯源凭据,必须将 GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES 环境变量设置为 1

如需生成可执行文件溯源工作负载身份配置,请运行以下命令:

# Generate a configuration file for executable-sourced credentials.
gcloud iam workload-identity-pools create-cred-config \
    projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>PROVIDER_ID</var> \
    --service-account=<var>SERVICE_ACCOUNT_EMAIL</var> \
    --subject-token-type=<var>SUBJECT_TOKEN_TYPE</var> \
    # The absolute path for the program, including arguments.
    # e.g. --executable-command="/path/to/command --foo=bar"
    --executable-command=<var>EXECUTABLE_COMMAND</var> \
    # Optional argument for the executable timeout. Defaults to 30s.
    # --executable-timeout-millis=<var>EXECUTABLE_TIMEOUT</var> \
    # Optional argument for the absolute path to the executable output file.
    # See below on how this argument impacts the library behaviour.
    # --executable-output-file=<var>EXECUTABLE_OUTPUT_FILE</var> \
    --output-file /path/to/generated/config.json

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • PROVIDER_ID:OIDC 或 SAML 提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。
  • SUBJECT_TOKEN_TYPE:主题令牌类型。
  • EXECUTABLE_COMMAND:要运行的完整命令,包括实参。 必须是程序的绝对路径。

--executable-timeout-millis 标志是可选的;它指定了身份验证库等待可执行文件完成的持续时间(以毫秒为单位)。如果未提供,则默认为 30 秒。允许的最大值为 2 分钟,最小值为 5 秒。

可选的 --executable-output-file 标志用于指定缓存可执行文件的第三方凭据响应的路径。缓存有助于提高性能,因为身份验证库会先检查此文件是否包含有效且未过期的凭据,然后再运行可执行文件。如果存在有效的缓存凭据,库会使用这些凭据,从而避免不必要的可执行文件运行。

可执行文件必须将凭据响应写入此文件。身份验证库仅从此位置读取数据。文件内容必须与预期 JSON 格式一致。

为了检索第三方令牌,该库将使用指定的命令运行可执行文件。可执行文件的输出必须遵循以下示例中指定的响应格式,并且必须将响应输出到 stdout

以下是可执行的 OIDC 成功响应示例:

{
  "version": 1,
  "success": true,
  "token_type": "urn:ietf:params:oauth:token-type:id_token",
  "id_token": "HEADER.PAYLOAD.SIGNATURE",
  "expiration_time": 1620499962
}

以下是可执行的 SAML 成功响应示例:

{
  "version": 1,
  "success": true,
  "token_type": "urn:ietf:params:oauth:token-type:saml2",
  "saml_response": "...",
  "expiration_time": 1620499962
}

如果您在凭证配置中使用 --executable-output-file 实参指定输出文件,则成功的可执行文件响应必须包含 expiration_time 字段。这样,身份验证库便可有效地缓存和管理存储在该文件中的凭据的有效性。

以下是可执行错误响应的示例:

{
  "version": 1,
  "success": false,
  "code": "401",
  "message": "Caller not authorized."
}

这些字段都是错误响应的必填字段。该库使用代码和消息字段作为抛出异常的一部分。

响应格式字段摘要: * version:JSON 输出的版本。仅支持版本 1。 * success: 如果为 true,则响应必须包含第三方令牌和令牌类型。如果在凭据配置中指定了输出文件,则响应还必须包含 expiration_time 字段。可执行文件还必须以退出代码 0 退出。如果为 false,则响应必须包含错误代码和消息字段,并以非零值退出。 * token_type: 此字段指定了第三方主题令牌类型。必须为 urn:ietf:params:oauth:token-type:jwturn:ietf:params:oauth:token-type:id_tokenurn:ietf:params:oauth:token-type:saml2。* id_token: 第三方 OIDC 令牌。 * saml_response:第三方 SAML 响应。 * expiration_time: 第三方主题令牌的到期时间(以秒为单位,与 Unix 计时原点之间相隔的秒数)。 * code:错误代码字符串。 * message:错误消息。

所有响应类型都必须包含 versionsuccess 字段。* 成功响应必须包含 token_typeid_tokensaml_response 之一。如果在凭据配置中指定了输出文件,则还必须包含 expiration_time 字段。 * 错误响应必须同时包含 codemessage 字段。

库在运行可执行文件时会填充以下环境变量:

  • GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE:凭据配置中的目标对象字段。始终存在。
  • GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE: 相应的主题令牌类型。 始终存在。
  • GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL:服务账号电子邮件地址。仅当使用服务账号模拟时存在。
  • GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE:凭据配置中的输出文件位置。仅当在凭据配置中指定了该位置时存在。

可执行文件可以使用这些环境变量来避免对这些值进行硬编码。

安全注意事项

建议采取以下安全措施:

  • 防止恶意进程运行可执行文件,因为该文件会通过 stdout 将敏感凭据输出到这些进程及其用户。
  • 防止恶意进程更改配置或可执行文件的调用。

由于使用可执行文件来源的凭据非常复杂,因此我们强烈建议您使用其他受支持的机制(例如文件或网址来源)来提供第三方凭据,除非这些机制无法满足您的特定要求。

您现在可以使用 Auth 库来调用 OIDC 或 SAML 提供方的Google Cloud 资源。

将自定义供应商与 OIDC 和 SAML 搭配使用

在构建 IdentityPoolCredentials 时,可以使用 IdentityPoolSubjectTokenSupplier 的自定义实现来提供可交换为 Google Cloud 访问令牌的主题令牌。当 Google Cloud凭据调用供应商时,供应商必须返回有效的未过期正文令牌。

IdentityPoolCredentials 不会缓存返回的令牌,因此请在令牌提供程序中实现缓存逻辑,以防止针对同一主题令牌发出多个请求。

import java.io.IOException;

public class CustomTokenSupplier implements IdentityPoolSubjectTokenSupplier {

  @Override
  public String getSubjectToken(ExternalAccountSupplierContext context) throws IOException {
    // Any call to the supplier passes a context object with the requested
    // audience and subject token type.
    string audience = context.getAudience();
    string tokenType = context.getSubjectTokenType();

    try {
      // Return a valid, unexpired token for the requested audience and token type.
      // Note that IdentityPoolCredentials don't cache the subject token so
      // any caching logic needs to be implemented in the token supplier.
      return retrieveToken(audience, tokenType);
    } catch (Exception e) {
      // If token is unavailable, throw IOException.
      throw new IOException(e);
    }
  }

  private String retrieveToken(string tokenType, string audience) {
    // Retrieve a subject token of the requested type for the requested audience.
  }
}
CustomTokenSupplier tokenSupplier = new CustomTokenSupplier();
IdentityPoolCredentials identityPoolCredentials =
    IdentityPoolCredentials.newBuilder()
        .setSubjectTokenSupplier(tokenSupplier) // Sets the token supplier.
        .setAudience(...) // Sets the Google Cloud audience.
        .setSubjectTokenType(SubjectTokenTypes.JWT) // Sets the subject token type.
        .build();

其中,受众群体是指:

//iam.googleapis.com/projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>WORKLOAD_POOL_ID</var>/providers/<var>PROVIDER_ID</var>

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • WORKLOAD_POOL_ID:工作负载身份池 ID。
  • PROVIDER_ID:提供方 ID。

您还可以通过使用 gcloud CLI 生成凭据配置文件来查找受众群体、服务账号模拟网址和任何其他构建器字段的值。

将自定义供应商与 AWS 搭配使用

初始化 AwsCredentials 时,可以提供 AwsSecurityCredentialsSupplier 的自定义实现。如果提供,AwsCredentials 实例将延迟到供应商检索 AWS 安全凭据以换取Google Cloud 访问令牌。当被 Google Cloud 凭据调用时,提供程序必须返回有效且未过期的 AWS 安全凭据。

AwsCredentials 不会缓存返回的 AWS 安全凭据或区域,因此请在提供程序中实现缓存逻辑,以防止对同一资源发出多个请求。

class CustomAwsSupplier implements AwsSecurityCredentialsSupplier {
  @Override
  AwsSecurityCredentials getAwsSecurityCredentials(ExternalAccountSupplierContext context) throws IOException {
    // Any call to the supplier passes a context object with the requested
    // audience.
    String audience = context.getAudience();

    try {
      // Return valid, unexpired AWS security credentials for the requested audience.
      // Note that AwsCredentials don't cache the AWS security credentials so
      // any caching logic needs to be implemented in the credentials' supplier.
      return retrieveAwsSecurityCredentials(audience);
    } catch (Exception e) {
      // If credentials are unavailable, throw IOException.
      throw new IOException(e);
    }
  }

  @Override
  String getRegion(ExternalAccountSupplierContext context) throws IOException {
    try {
      // Return a valid AWS region. i.e. "us-east-2".
      // Note that AwsCredentials don't cache the region so
      // any caching logic needs to be implemented in the credentials' supplier.
      return retrieveAwsRegion();
    } catch (Exception e) {
      // If region is unavailable, throw IOException.
      throw new IOException(e);
    }
  }

  private AwsSecurityCredentials retrieveAwsSecurityCredentials(string audience) {
    // Retrieve Aws security credentials for the requested audience.
  }

  private String retrieveAwsRegion() {
    // Retrieve current AWS region.
  }
}
CustomAwsSupplier awsSupplier = new CustomAwsSupplier();
AwsCredentials credentials = AwsCredentials.newBuilder()
    .setSubjectTokenType(SubjectTokenTypes.AWS4) // Sets the subject token type.
    .setAudience(...) // Sets the Google Cloud audience.
    .setAwsSecurityCredentialsSupplier(supplier) // Sets the supplier.
    .build();

受众群体//iam.googleapis.com/projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>WORKLOAD_POOL_ID</var>/providers/<var>PROVIDER_ID</var>

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • WORKLOAD_POOL_ID:工作负载身份池 ID。
  • PROVIDER_ID:提供方 ID。

您还可以通过使用 gcloud CLI 生成凭据配置文件来查找受众群体、服务账号模拟网址和任何其他构建器字段的值。

可配置的令牌生命周期

使用服务账号模拟通过工作负载身份联合创建凭据配置时,您可以提供一个可选实参来配置服务账号访问令牌的生命周期。

如需生成具有可配置令牌有效期的配置,请运行以下命令(此示例使用 AWS 配置,但可以为所有工作负载身份联合提供方配置令牌有效期):

  # Generate an AWS configuration file with configurable token lifetime.
  gcloud iam workload-identity-pools create-cred-config \
      projects/<var>PROJECT_NUMBER</var>/locations/global/workloadIdentityPools/<var>POOL_ID</var>/providers/<var>AWS_PROVIDER_ID</var> \
      --service-account <var>SERVICE_ACCOUNT_EMAIL</var> \
      --aws \
      --output-file /path/to/generated/config.json \
      --service-account-token-lifetime-seconds <var>TOKEN_LIFETIME</var>

替换以下内容:

  • PROJECT_NUMBER: Google Cloud 项目编号。
  • POOL_ID:工作负载身份池 ID。
  • AWS_PROVIDER_ID:AWS 提供方 ID。
  • SERVICE_ACCOUNT_EMAIL:要模拟的服务账号的电子邮件地址。
  • TOKEN_LIFETIME:所选的服务账号访问令牌的有效时长(以秒为单位)。

service-account-token-lifetime-seconds 标志是可选的。如果未提供,则该标志的默认值为 1 小时。允许的最小值是 600(10 分钟),允许的最大值是 43200(12 小时)。 如果需要超过一小时的有效时长,您必须在强制执行 constraints/iam.allowServiceAccountCredentialLifetimeExtension 限制条件的组织政策服务中将该服务账号添加为允许值。

如果配置较短的生命周期(例如 10 分钟),会导致库每 10 分钟启动一次完整的令牌交换流程。即使第三方令牌未过期,也会调用第三方令牌提供程序。

使用外部账号授权用户员工凭据

借助外部账号授权用户凭证,您可以使用 gcloud CLI 通过网络浏览器登录外部身份提供方账号,并为身份验证库创建要使用的配置。

如需生成外部账号授权用户员工身份配置,请运行以下命令:

gcloud auth application-default login --login-config=LOGIN_CONFIG

其中,需要替换以下变量:

系统会打开一个浏览器流程,供您使用已配置的第三方身份提供方登录。然后,它会将外部账号授权用户配置存储在熟知的 ADC 位置。

然后,身份验证库将使用配置中提供的刷新令牌生成和刷新访问令牌,以调用 Google Cloud 服务。

刷新令牌的默认生命周期为 1 小时。之后,您需要通过 gcloud CLI 生成新的配置。您可以通过更改员工池的会话时长来修改有效期限,最长可设置为 12 小时。

使用外部身份

您可以将外部身份与 Application Default Credentials 搭配使用。如需将外部身份与应用默认凭据搭配使用,请按照工作负载身份联合部分中的说明,为您的外部身份生成 JSON 凭据配置文件。生成后,将此文件的路径存储在 GOOGLE_APPLICATION_CREDENTIALS 环境变量中。

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json

现在,该库可以选择正确的客户端类型,并从配置文件提供的上下文中初始化凭据。

GoogleCredentials googleCredentials = GoogleCredentials.getApplicationDefault();

String projectId = "your-project-id";
String url = "https://storage.googleapis.com/storage/v1/b?project=" + projectId;

HttpCredentialsAdapter credentialsAdapter = new HttpCredentialsAdapter(googleCredentials);
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(credentialsAdapter);
HttpRequest request = requestFactory.buildGetRequest(new GenericUrl(url));

JsonObjectParser parser = new JsonObjectParser(GsonFactory.getDefaultInstance());
request.setParser(parser);

HttpResponse response = request.execute();
System.out.println(response.parseAsString());

您还可以使用生成的配置文件显式初始化外部账号客户端。

ExternalAccountCredentials credentials =
    ExternalAccountCredentials.fromStream(new FileInputStream("/path/to/credentials.json"));

安全注意事项

此库不会对凭据配置的 token_urltoken_info_urlservice_account_impersonation_url 字段执行任何验证。我们不建议您使用未使用 gcloud CLI 生成的凭据配置,除非您验证过网址字段指向的是 googleapis.com 网域。

使用凭据访问边界缩小权限范围

通过凭据访问边界缩小权限范围,可以限制短期有效的凭据可以使用的 Cloud Storage Identity and Access Management (IAM) 权限。这需要创建一个 CredentialAccessBoundary,用于定义适用于降级范围令牌的限制。使用降级凭据可确保传输中的令牌始终具有最低权限。请参阅最小权限原则

创建 CredentialAccessBoundary

凭据访问边界用于指定新创建的凭据可以访问哪些资源。它还指定了每个资源可用权限的上限。它包含一个或多个 AccessBoundaryRule 对象。

以下代码段展示了如何使用一个 AccessBoundaryRule 初始化 CredentialAccessBoundary。此规则指定,降权后的令牌将对存储桶 bucket-123 中以 customer-a 开头的对象具有只读访问权限。

// Create the AccessBoundaryRule.
String availableResource = "//storage.googleapis.com/projects/_/buckets/bucket-123";
String availablePermission = "inRole:roles/storage.objectViewer";
String expression =  "resource.name.startsWith('projects/_/buckets/bucket-123/objects/customer-a')";

CredentialAccessBoundary.AccessBoundaryRule rule =
    CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
        .setAvailableResource(availableResource)
        .addAvailablePermission(availablePermission)
        .setAvailabilityCondition(
        CredentialAccessBoundary.AccessBoundaryRule.AvailabilityCondition.newBuilder().setExpression(expression).build())
        .build();

// Create the CredentialAccessBoundary with the rule.
CredentialAccessBoundary credentialAccessBoundary =
        CredentialAccessBoundary.newBuilder().addRule(rule).build();

常见使用模式

常见的使用模式涉及具有提升访问权限的令牌代理。此代理会根据具有较高访问权限的源凭据生成具有缩小权限范围的凭据。然后,它通过安全的经过身份验证的渠道将具有缩小权限范围的短期有效访问令牌传递给令牌使用方,以有限访问 Google CloudStorage 资源。

生成范围缩减的令牌

您可以通过以下两种方式使用 CredentialAccessBoundary 生成具有缩小权限范围的令牌:

  • 服务器端(使用 DownscopedCredentials:每次需要缩小权限范围的令牌时,客户端都会调用 Security Token Service (STS)。这适用于凭据访问边界规则更改不频繁的应用,或者您多次重复使用单个缩小范围的凭据的应用。需要重点考虑的是,每次更改规则都需要您向 STS 发出新的调用。此方法可在 google-auth-library-oauth2-http 库中使用,不需要任何其他依赖项。这样可以简化集成流程。如果您的使用情形不需要客户端方法的特定优势,那么这是一个不错的选择。

  • 客户端(使用 ClientSideCredentialAccessBoundaryFactory:客户端检索一次加密材料,然后在本地生成多个降权令牌。这样可以最大限度地减少对 STS 的调用,并且在凭证访问边界规则频繁更改时效率更高,因为客户端无需针对每次规则更改都与 STS 联系。对于需要生成多个具有缩小权限范围的唯一令牌的应用,这种方法也更高效。此方法在 google-auth-library-cab-token-generator 模块中可用。不过,此模块自带一组依赖项。这些依赖项可能会增加项目的复杂性。如果您的主要考虑因素是最大限度地减少 STS 调用次数并生成大量唯一令牌,请考虑采用此方法。 您还需要管理其他依赖项。

服务器端 CAB

DownscopedCredentials 类可用于根据源凭据和 CredentialAccessBoundary 生成缩小范围的访问令牌。

// Retrieve the source credentials from ADC.
GoogleCredentials sourceCredentials = GoogleCredentials.getApplicationDefault()
        .createScoped("https://www.googleapis.com/auth/cloud-platform");

// Create an Access Boundary Rule which will restrict the downscoped token to having read-only
// access to objects starting with "customer-a" in bucket "bucket-123".
String availableResource = "//storage.googleapis.com/projects/_/buckets/bucket-123";
String availablePermission = "inRole:roles/storage.objectViewer";
String expression =  "resource.name.startsWith('projects/_/buckets/bucket-123/objects/customer-a')";

CredentialAccessBoundary.AccessBoundaryRule rule =
    CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
        .setAvailableResource(availableResource)
        .addAvailablePermission(availablePermission)
        .setAvailabilityCondition(
            new AvailabilityCondition(expression, /* title= */ null, /* description= */ null))
        .build();

// Initialize the DownscopedCredentials class.
DownscopedCredentials downscopedCredentials =
    DownscopedCredentials.newBuilder()
        .setSourceCredential(sourceCredentials)
        .setCredentialAccessBoundary(CredentialAccessBoundary.newBuilder().addRule(rule).build())
        .build();

// Retrieve the downscoped access token.
// You will need to pass this to the Token Consumer.
AccessToken downscopedAccessToken = downscopedCredentials.refreshAccessToken();

客户端 CAB

对于客户端 CAB,ClientSideCredentialAccessBoundaryFactory 与来源凭据一起使用。初始化工厂后,可以反复调用 generateToken() 方法并使用不同的 CredentialAccessBoundary 对象来创建多个降权令牌。

// Retrieve the source credentials from ADC.
GoogleCredentials sourceCredentials = GoogleCredentials.getApplicationDefault()
        .createScoped("https://www.googleapis.com/auth/cloud-platform");

// Create an Access Boundary Rule which will restrict the downscoped token to having read-only
// access to objects starting with "customer-a" in bucket "bucket-123".
String availableResource = "//storage.googleapis.com/projects/_/buckets/bucket-123";
String availablePermission = "inRole:roles/storage.objectViewer";
String expression =  "resource.name.startsWith('projects/_/buckets/bucket-123/objects/customer-a')";

CredentialAccessBoundary.AccessBoundaryRule rule =
    CredentialAccessBoundary.AccessBoundaryRule.newBuilder()
        .setAvailableResource(availableResource)
        .addAvailablePermission(availablePermission)
        .setAvailabilityCondition(
            new AvailabilityCondition(expression, /* title= */ null, /* description= */ null))
        .build();

// Initialize the ClientSideCredentialAccessBoundaryFactory.
ClientSideCredentialAccessBoundaryFactory factory =
    ClientSideCredentialAccessBoundaryFactory.newBuilder()
        .setSourceCredential(sourceCredentials)
        .build();

// Create the CredentialAccessBoundary with the rule.
CredentialAccessBoundary credentialAccessBoundary =
        CredentialAccessBoundary.newBuilder().addRule(rule).build();

// Generate the downscoped access token.
// You will need to pass this to the Token Consumer.
AccessToken downscopedAccessToken = factory.generateToken(credentialAccessBoundary);

使用缩小权限范围的访问令牌

您可以在专用网络中的服务器上设置令牌代理。同一网络中的各种工作负载(令牌使用方)向该代理发送经过身份验证的请求,以获取具有缩小权限范围的令牌。这些令牌允许他们访问或修改特定的 Google Cloud 存储分区。

代理会实例化具有缩小权限范围的凭据实例,这些实例可以生成短期有效的具有缩小权限范围的访问令牌。然后,它会将这些令牌传递给令牌使用者。

令牌使用方可以使用 OAuth2CredentialsOAuth2CredentialsWithRefresh 来使用这些具有缩小权限范围的访问令牌。然后,您可以使用此凭据初始化存储客户端实例,以访问受限的 Google Cloud存储资源。

// You can pass an `OAuth2RefreshHandler` to `OAuth2CredentialsWithRefresh` that will allow the
// library to seamlessly handle downscoped token refreshes on expiration.
OAuth2CredentialsWithRefresh.OAuth2RefreshHandler handler =
        new OAuth2CredentialsWithRefresh.OAuth2RefreshHandler() {
    @Override
    public AccessToken refreshAccessToken() {
      // Retrieve the token from your Token Broker.
      return accessToken;
    }
};

// The downscoped token is retrieved from the token broker.
AccessToken downscopedToken = handler.refreshAccessToken();

// Build the OAuth2CredentialsWithRefresh from the downscoped token and pass a refresh handler
// to handle token expiration. Passing the original downscoped token or the expiry here is optional,
// because the refresh_handler will generate the downscoped token on demand.
OAuth2CredentialsWithRefresh credentials =
    OAuth2CredentialsWithRefresh.newBuilder()
        .setAccessToken(downscopedToken)
        .setRefreshHandler(handler)
        .build();

// Use the credentials with the Cloud Storage SDK.
StorageOptions options = StorageOptions.newBuilder().setCredentials(credentials).build();
Storage storage = options.getService();

// Call Cloud Storage APIs.
// Because we passed the downscoped credential, we will have limited read-only access to objects
// starting with "customer-a" in bucket "bucket-123".
storage.get(...)

只有 Cloud Storage 支持凭据访问边界;其他Google Cloud 服务不支持此功能。

使用 google-http-client 的凭据

com.google.auth:google-auth-library-oauth2-http 提供的凭据可与 Google 基于 HTTP 的客户端搭配使用。Google 基于 HTTP 的客户端提供了一个 HttpCredentialsAdapter,可用作其构建器的最后一个实参 HttpRequestInitializer

import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.services.bigquery.Bigquery;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;

GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);

Bigquery bq = new Bigquery.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
    .setApplicationName(APPLICATION_NAME)
    .build();

验证 JWT 令牌(Beta 版功能)

如需验证 JWT 令牌,请使用 TokenVerifier 类。

验证签名

如需验证签名,请使用默认的 TokenVerifier

import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.auth.oauth2.TokenVerifier;

TokenVerifier tokenVerifier = TokenVerifier.newBuilder().build();
try {
  JsonWebSignature jsonWebSignature = tokenVerifier.verify(tokenString);
  // Optionally, verify additional claims.
  if (!"expected-value".equals(jsonWebSignature.getPayload().get("additional-claim"))) {
    // Handle custom verification error.
  }
} catch (TokenVerifier.VerificationException e) {
  // The token is invalid.
}

自定义 TokenVerifier

如需自定义 TokenVerifier,请使用其构建器实例化该对象:

import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.auth.oauth2.TokenVerifier;

TokenVerifier tokenVerifier = TokenVerifier.newBuilder()
  .setAudience("audience-to-verify")
  .setIssuer("issuer-to-verify")
  .build();
try {
  JsonWebSignature jsonWebSignature = tokenVerifier.verify(tokenString);
  // Optionally, verify additional claims.
  if (!"expected-value".equals(jsonWebSignature.getPayload().get("additional-claim"))) {
    // Handle custom verification error.
  }
} catch (TokenVerifier.VerificationException e) {
  // The token is invalid.
}

如需了解更多选项,请参阅 TokenVerifier.Builder 文档。

google-auth-library-credentials

此制品包含 Google 凭据的基本类和接口:

  • Credentials:这是授权身份的基类。 此类别的实现可以授权您的应用。
  • RequestMetadataCallback:这是用于接收异步 Credentials.getRequestMetadata(URI, Executor, RequestMetadataCallback) 结果的回调的接口。
  • ServiceAccountSigner:这是服务账号签名者的接口。 此类的实现能够使用与 Google 服务账号关联的凭据对字节数组进行签名。

google-auth-library-appengine

此制品依赖于 App Engine SDK (appengine-api-1.0-sdk)。仅当应用在采用 urlfetch 的 App Engine 环境中运行时,才使用此制品。借助 AppEngineCredentials 类,您可以根据 AppIdentityService 的实例授权您的 App Engine 应用。

用法:

import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import com.google.auth.Credentials;
import com.google.auth.appengine.AppEngineCredentials;

AppIdentityService appIdentityService = AppIdentityServiceFactory.getAppIdentityService();

Credentials credentials =
    AppEngineCredentials.newBuilder()
        .setScopes(...)
        .setAppIdentityService(appIdentityService)
        .build();

google-auth-library-cab-token-generator

此模块提供 ClientSideCredentialAccessBoundaryFactory 类,可使用凭据访问边界在客户端生成具有缩小的权限范围的 Cloud Storage 令牌。此方法特别适用于需要频繁更改凭证访问边界规则或生成许多唯一降权令牌的应用,因为它可以最大限度地减少对 Security Token Service (STS) 的调用。如需查看使用示例,请参阅客户端 CAB 部分。此模块自带一组依赖项。评估客户端降权带来的好处是否超过了特定用例的复杂性。