获取 ID 令牌

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页面介绍了用于获取 Google 签名的 OpenID Connect (OIDC) ID 令牌的一些方法。您需要在以下身份验证使用场景中使用 Google 签名的 ID 令牌:

如需了解 ID 令牌的内容和有效期,请参阅 ID 令牌

ID 令牌具有其可用于的特定服务或应用,由其 aud 声明的值指定。本页面使用“目标服务”一词来指代可使用 ID 令牌向其进行身份验证的服务或应用。

获取 ID 令牌后,您可以将其添加到对目标服务的请求的 Authorization 标头中。

获取 ID 令牌的方法

获取 ID 令牌的方法有多种。本页介绍了以下几种方法:

Cloud Run 和 Cloud Functions 提供特定于服务的方法来获取 ID 令牌。如需了解详情,请参阅向 Cloud Run 或 Cloud Functions 上托管的应用进行身份验证

如果您需要 ID 令牌被不在 Google Cloud 上托管的应用接受,则或许可以使用这些方法,但您应该确定应用所需的 ID 令牌声明。

从元数据服务器获取 ID 令牌

如果您的代码在可以关联服务帐号的资源上运行,所关联服务的元数据服务器在大多数情况下都可以提供 ID 令牌。元数据服务器会为关联的服务帐号生成 ID 令牌。您无法从元数据服务器获取基于用户凭据的 ID 令牌。

您的代码在以下 Google Cloud 服务上运行时,您可以从元数据服务器获取 ID 令牌:

虽然 Cloud Build 也提供元数据服务器,但它不会返回 ID 令牌。

如需从元数据服务器检索 ID 令牌,您需要查询服务帐号的身份端点,如以下示例所示。

curl

AUDIENCE 替换为目标服务的 URI,例如 http://www.example.com

curl -H "Metadata-Flavor: Google" \
  'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=AUDIENCE'

PowerShell

AUDIENCE 替换为目标服务的 URI,例如 http://www.example.com

$value = (Invoke-RestMethod `
  -Headers @{'Metadata-Flavor' = 'Google'} `
  -Uri "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=AUDIENCE")
$value

Java

如需运行此代码示例,您必须安装 Java 版 Google API 客户端库


import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.auth.oauth2.IdTokenProvider;
import com.google.auth.oauth2.IdTokenProvider.Option;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;

public class IdTokenFromMetadataServer {

  public static void main(String[] args) throws IOException, GeneralSecurityException {
    // TODO(Developer): Replace the below variables before running the code.

    // The url or target audience to obtain the ID token for.
    String url = "https://example.com";

    getIdTokenFromMetadataServer(url);
  }

  // Use the Google Cloud metadata server to create an identity token and add it to the
  // HTTP request as part of an Authorization header.
  public static void getIdTokenFromMetadataServer(String url) throws IOException {
    // Construct the GoogleCredentials object which obtains the default configuration from your
    // working environment.
    GoogleCredentials googleCredentials = GoogleCredentials.getApplicationDefault();

    IdTokenCredentials idTokenCredentials =
        IdTokenCredentials.newBuilder()
            .setIdTokenProvider((IdTokenProvider) googleCredentials)
            .setTargetAudience(url)
            // Setting the ID token options.
            .setOptions(Arrays.asList(Option.FORMAT_FULL, Option.LICENSES_TRUE))
            .build();

    // Get the ID token.
    // Once you've obtained the ID token, you can use it to make an authenticated call to the
    // target audience.
    String idToken = idTokenCredentials.refreshAccessToken().getTokenValue();
    System.out.println("Generated ID token.");
  }
}

Python

如需运行此代码示例,您必须安装 Python 版 Google 身份验证库


import google
import google.oauth2.credentials
from google.auth import compute_engine
import google.auth.transport.requests

def idtoken_from_metadata_server(url: str):
    """
    Use the Google Cloud metadata server in the Cloud Run (or AppEngine or Kubernetes etc.,)
    environment to create an identity token and add it to the HTTP request as part of an
    Authorization header.

    Args:
        url: The url or target audience to obtain the ID token for.
            Examples: http://www.abc.com
    """

    request = google.auth.transport.requests.Request()
    # Set the target audience.
    # Setting "use_metadata_identity_endpoint" to "True" will make the request use the default application
    # credentials. Optionally, you can also specify a specific service account to use by mentioning
    # the service_account_email.
    credentials = compute_engine.IDTokenCredentials(
        request=request, target_audience=url, use_metadata_identity_endpoint=True
    )

    # Get the ID token.
    # Once you've obtained the ID token, use it to make an authenticated call
    # to the target audience.
    credentials.refresh(request)
    # print(credentials.token)
    print("Generated ID token.")

使用连接服务生成 ID 令牌

某些 Google Cloud 服务可帮助您调用其他服务。您可以借助这些连接服务来确定何时需进行调用或管理涉及调用服务的工作流。以下服务在调用需要 ID 令牌的服务时,会自动添加 ID 令牌,并包含相应的 aud 声明值:

Pub/Sub
Pub/Sub 支持服务之间的异步通信。您可以将 Pub/Sub 配置为在消息中包含 ID 令牌。如需了解详情,请参阅推送订阅身份验证
Tasks
借助 Tasks,您可以管理分布式任务的执行。您可以将任务配置为在调用服务时添加 ID 令牌或访问令牌。如需了解详情,请参阅将 HTTP 目标任务与身份验证令牌配合使用
Cloud Scheduler
Cloud Scheduler 是一项全代管式企业级 cron 作业调度服务。您可以将 Cloud Scheduler 配置为在调用其他服务时添加 ID 令牌或访问令牌。如需了解详情,请参阅对 HTTP 目标使用身份验证

通过模拟服务帐号生成 ID 令牌

借助服务帐号模拟,主帐号可为可信服务帐号生成短期有效凭据。然后,主帐号可以使用这些凭据以服务帐号的身份进行身份验证。

主帐号必须对服务帐号具有可启用模拟的 IAM 角色,才能模拟此服务帐号。如果主帐号本身是另一个服务帐号,则只需直接向该服务帐号提供所需的权限并使其模拟自身可能看起来更加容易。此配置(称为自模拟)会造成安全漏洞,因为它会让服务帐号创建可以永久刷新的访问令牌。

服务帐号模拟应始终涉及两个主帐号:代表调用方的主帐号,以及被模拟的服务帐号(称为具有权限的服务帐号)。

如需通过模拟服务帐号生成 ID 令牌,请按照以下步骤操作:

  1. 确定或创建服务帐号,使其成为具有权限的服务帐号。为该服务帐号授予目标服务所需的 IAM 角色:

    • 对于 Cloud Run 服务,请授予 Cloud Run Invoker 角色 (roles/run.invoker)。
    • 对于 Cloud Functions,请授予 Cloud Functions Invoker 角色 (roles/cloudfunctions.invoker)。
    • 如需了解其他目标服务,请参阅相应服务的产品文档。
  2. 确定将执行模拟的主帐号,并设置应用默认凭据 (ADC) 以使用此主帐号的凭据。

    对于开发环境,主帐号通常是您使用 gcloud CLI 提供给 ADC 的用户帐号。但是,如果您在关联有服务帐号的资源上运行,则关联的服务帐号是主帐号。

  3. 为主帐号授予模拟具有权限的服务帐号所需的角色。

    如需了解分步说明,请参阅 IAM 文档中的提供所需的权限

  4. 使用 IAM Credentials API 为已获授权的服务帐号生成 ID 令牌。

    如需了解分步说明,请参阅生成 OpenID Connect ID 令牌

使用外部身份提供方生成 ID 令牌

使用外部身份提供方生成 ID 令牌使用的是工作负载身份联合,让您可以设置 Google Cloud 与外部身份提供方之间的关系。然后,您可以使用外部身份提供方提供的凭据生成可在 Google Cloud 中使用的 ID 令牌或访问令牌。

如需为外部身份提供方提供的凭据生成 ID 令牌,请按照以下步骤操作:

  1. 确定或创建服务帐号,以提供调用目标服务所需的 IAM 角色。

    最佳实践是专门为此目的创建一个服务帐号,并为其只提供所需的角色。此方法遵循最小权限原则。

  2. 确定调用目标服务所需的角色。向目标服务上的服务帐号授予以下角色:

    • 对于 Cloud Run 服务,请授予 Cloud Run Invoker 角色 (roles/run.invoker)。
    • 对于 Cloud Functions,请授予 Cloud Functions Invoker 角色 (roles/cloudfunctions.invoker)。
    • 如需了解其他目标服务,请参阅相应服务的产品文档。
  3. 按照配置工作负载身份联合所述,为您的身份提供方配置工作负载身份联合。

  4. 按照授予外部身份模拟服务帐号的权限中的说明执行操作。将您在上述步骤中设置的服务帐号用作要模拟的服务帐号。

  5. 使用 REST API 获取短期有效的令牌,但对于最后一步,请改用 generateIdToken 方法获取 ID 令牌:

    Bash

    ID_TOKEN=$(curl -0 -X POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateIdToken \
        -H "Content-Type: text/json; charset=utf-8" \
        -H "Authorization: Bearer $STS_TOKEN" \
        -d @- <<EOF | jq -r .token
        {
            "audience": "AUDIENCE"
        }
    EOF
    )
    echo $ID_TOKEN
    

    PowerShell

    $IdToken = (Invoke-RestMethod `
        -Method POST `
        -Uri "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateIdToken" `
        -Headers @{ "Authorization" = "Bearer $StsToken" } `
        -ContentType "application/json" `
        -Body (@{
            "audience" = "AUDIENCE"
        } | ConvertTo-Json)).token
    Write-Host $IdToken
    

    请替换以下内容:

    • SERVICE_ACCOUNT_EMAIL:服务帐号的电子邮件地址
    • AUDIENCE:该令牌的受众群体,例如使用该令牌访问的应用或服务

后续步骤