取得 ID 權杖

本頁說明取得 Google 簽署的 OpenID Connect (OIDC) ID 權杖的幾種方式。

在下列驗證用途中,您需要 Google 簽署的 ID 權杖:

如要瞭解 ID 權杖內容和生命週期,請參閱「ID 權杖」。

身分符記只能用於特定服務或應用程式,這類服務或應用程式是由符記的 aud 聲明值指定。本頁面使用「目標服務」一詞,是指可用於驗證 ID 權杖的服務或應用程式。

取得 ID 權杖後,您可以在向目標服務提出要求的 Authorization 標頭中加入該權杖。

取得 ID 權杖的方法

取得 ID 權杖的方式有很多種。本頁面說明下列方法:

如果應用程式並非託管於Google Cloud,但您需要應用程式接受 ID 權杖,或許可以使用這些方法。不過,您應判斷應用程式需要哪些 ID 權杖聲明。

從中繼資料伺服器取得 ID 權杖

當程式碼在可附加服務帳戶的資源上執行時,相關聯服務的中繼資料伺服器通常會提供 ID 權杖。中繼資料伺服器會為附加的服務帳戶產生 ID 權杖。您無法從中繼資料伺服器取得以使用者憑證為依據的 ID 權杖。

在下列 Google Cloud 服務上執行程式碼時,您可以從中繼資料伺服器取得 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 專用的 Auth 用戶端程式庫


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.");
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	"golang.org/x/oauth2/google"
	"google.golang.org/api/idtoken"
	"google.golang.org/api/option"
)

// getIdTokenFromMetadataServer uses the Google Cloud metadata server environment
// to create an identity token and add it to the HTTP request as part of an Authorization header.
func getIdTokenFromMetadataServer(w io.Writer, url string) error {
	// url := "http://www.example.com"

	ctx := context.Background()

	// Construct the GoogleCredentials object which obtains the default configuration from your
	// working environment.
	credentials, err := google.FindDefaultCredentials(ctx)
	if err != nil {
		return fmt.Errorf("failed to generate default credentials: %w", err)
	}

	ts, err := idtoken.NewTokenSource(ctx, url, option.WithCredentials(credentials))
	if err != nil {
		return fmt.Errorf("failed to create NewTokenSource: %w", err)
	}

	// Get the ID token.
	// Once you've obtained the ID token, you can use it to make an authenticated call
	// to the target audience.
	_, err = ts.Token()
	if err != nil {
		return fmt.Errorf("failed to receive token: %w", err)
	}
	fmt.Fprintf(w, "Generated ID token.\n")

	return nil
}

Node.js

如要執行這個程式碼範例,您必須安裝 Node.js 適用的 Google Auth 程式庫

/**
 * TODO(developer):
 *  1. Uncomment and replace these variables before running the sample.
 */
// const targetAudience = 'http://www.example.com';

const {GoogleAuth} = require('google-auth-library');

async function getIdTokenFromMetadataServer() {
  const googleAuth = new GoogleAuth();

  const client = await googleAuth.getIdTokenClient(targetAudience);

  // Get the ID token.
  // Once you've obtained the ID token, you can use it to make an authenticated call
  // to the target audience.
  await client.idTokenProvider.fetchIdToken(targetAudience);
  console.log('Generated ID token.');
}

getIdTokenFromMetadataServer();

Python

如要執行這個程式碼範例,請務必安裝 Google Auth Python 程式庫


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.example.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.")

Ruby

如要執行這個程式碼範例,請務必安裝 Ruby 適用的 Google Auth 程式庫

require "googleauth"

##
# Uses the Google Cloud metadata server environment to create an identity token
# and add it to the HTTP request as part of an Authorization header.
#
# @param url [String] The url or target audience to obtain the ID token for
#   (e.g. "http://www.example.com")
#
def auth_cloud_idtoken_metadata_server url:
  # Create the GCECredentials client.
  id_client = Google::Auth::GCECredentials.new target_audience: url

  # Get the ID token.
  # Once you've obtained the ID token, you can use it to make an authenticated call
  # to the target audience.
  id_client.fetch_access_token
  puts "Generated ID token."

  id_client.refresh!
end

使用連結服務產生 ID 權杖

部分 Google Cloud 服務可協助您呼叫其他服務。這些連結服務可能有助於判斷通話時間,或管理包含呼叫服務的工作流程。下列服務在發起對需要 ID 符記的服務的呼叫時,可以自動加入 ID 符記,並為 aud 聲明提供適當的值:

Cloud Scheduler
Cloud Scheduler 是全代管的企業級 Cron 工作排程器。您可以設定 Cloud Scheduler,在叫用其他服務時加入 ID 權杖或存取權杖。詳情請參閱 使用驗證搭配 HTTP 目標
Cloud Tasks
Cloud Tasks 可讓您管理分散式工作的執行作業。您可以設定工作,在呼叫服務時加入 ID 權杖或存取權杖。詳情請參閱 使用驗證憑證搭配 HTTP 目標工作
Pub/Sub
Pub/Sub 可讓服務之間進行非同步通訊。 您可以設定 Pub/Sub,在訊息中加入 ID 權杖。詳情請參閱「 推送訂閱的驗證」。
工作流程
Workflows 是一個全代管的自動化調度管理平台,可以按照您定義的順序執行服務,也就是「工作流程」。您可以定義工作流程,在工作流程叫用其他服務時加入 ID 權杖或存取權杖。詳情請參閱「 從工作流程提出經過驗證的要求」。

模擬服務帳戶來產生 ID 權杖

服務帳戶模擬功能可讓主體為信任的服務帳戶產生短期憑證。主體隨後可以使用這些憑證,以服務帳戶身分進行驗證。

主體必須具備服務帳戶的 IAM 角色,才能模擬該服務帳戶。如果主體是另一個服務帳戶,直接為該服務帳戶提供必要權限,並允許服務帳戶模擬自身,似乎會比較簡單。這種設定稱為「自我模擬」,會造成安全漏洞,因為服務帳戶可以建立可無限期重新整理的存取權杖。

服務帳戶模擬功能一律涉及兩個主體:代表呼叫者的主體,以及要模擬的服務帳戶 (稱為具備權限的服務帳戶)。

如要模擬服務帳戶來產生 ID 權杖,請按照下列一般程序操作。

如需逐步操作說明,請參閱「建立 ID 權杖」一文。

  1. 找出或建立服務帳戶,做為具有權限的服務帳戶。

  2. 找出呼叫目標服務所需的角色。在目標服務中,將下列角色授予服務帳戶:

    • 如果是 Cloud Run 服務,請授予 Cloud Run 叫用者角色 (roles/run.invoker)。
    • 如果是 Cloud Run functions,請授予 Cloud Functions 叫用者角色 (roles/cloudfunctions.invoker)。
    • 如需其他目標服務,請參閱該服務的產品說明文件。
  3. 找出要執行模擬作業的主體,並設定應用程式預設憑證 (ADC),以便使用這個主體的憑證。

    在開發環境中,主體通常是您使用 gcloud CLI 提供給 ADC 的使用者帳戶。不過,如果您在附加服務帳戶的資源上執行作業,附加的服務帳戶就是主體。

  4. 將服務帳戶 OpenID Connect 身分識別權杖建立者角色 (roles/iam.serviceAccountOpenIdTokenCreator) 授予主體。

  5. 使用 IAM Credentials API 為已授權的服務帳戶產生 ID 權杖。

    更改下列內容:

    • AUDIENCE:目標服務的 URI,例如 http://www.example.com
    • SERVICE_ACCOUNT_EMAIL:具有權限的服務帳戶電子郵件地址。
    curl -X POST \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -d '{"audience": "AUDIENCE", "includeEmail": "true"}' \
    https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateIdToken
    

產生通用 ID 權杖,以便使用 Cloud Run 和 Cloud Run 函式進行開發

您可以使用 gcloud CLI 取得使用者憑證的 ID 權杖,並搭配任何 Cloud Run 服務或 Cloud Run 函式使用,前提是呼叫端必須具備必要的 IAM 權限才能叫用。這個權杖不適用於其他應用程式。

後續步驟