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 でホストされているアプリケーションの認証をご覧ください。

Google Cloud でホストされていないアプリケーションで ID トークンを受け入れる必要がある場合は、多くの場合でこれらの方法を使用できますが、アプリケーションに必要な ID トークンのクレームを決定する必要があります。

メタデータ サーバーから ID トークンを取得する

通常、サービス アカウントを接続できるリソースでコードが実行されている場合、関連付けられたサービスのメタデータ サーバーから ID トークンが提供されます。メタデータ サーバーが、接続されているサービス アカウントの ID トークンを生成します。メタデータ サーバーからユーザー認証情報に基づく ID トークンを取得することはできません。

コードが次の Google Cloud サービスで実行されている場合、メタデータ サーバーから ID トークンを取得できます。

メタデータ サーバーから 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.");
  }
}

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

/**
 * 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 認証ライブラリをインストールする必要があります。

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 トークンを必要とするサービスの呼び出しを開始するときに、aud クレームに適切な値が設定された ID トークンを自動的に含めることができます。

Cloud Scheduler
Cloud Scheduler は、エンタープライズ クラスのフルマネージド cron ジョブ スケジューラです。別のサービスを呼び出すときに、ID トークンまたはアクセス トークンのいずれかを含めるように Cloud Scheduler を構成できます。詳細については、HTTP ターゲットでの認証の使用をご覧ください。
Cloud Tasks
Cloud Tasks を使用すると、分散タスクの実行を管理できます。ID トークンまたはアクセス トークンのいずれかをサービスの呼び出し時に含めるようにタスクを構成できます。詳細については、認証トークンを使用した HTTP ターゲット タスクの使用をご覧ください。
Pub/Sub
Pub/Sub を使用すると、サービス間で非同期通信を行うことができます。Pub/Sub は、メッセージに ID トークンを含めるように構成できます。詳細については、push サブスクリプションの認証をご覧ください。
Workflows
Workflows は、フルマネージドのオーケストレーション プラットフォームで、定義した順序(ワークフロー)でサービスを実行します。別のサービスを呼び出すときに、ID トークンまたはアクセス トークンのいずれかを含めるようにワークフローを定義できます。詳細については、ワークフローから認証済みリクエストを行うをご覧ください。

サービス アカウントの権限を借用して ID トークンを生成する

サービス アカウントの権限を借用することで、プリンシパルは、信頼できるサービス アカウントに有効期間の短い認証情報を生成できます。プリンシパルは、これらの認証情報を使用してサービス アカウントとして認証できます。

プリンシパルがサービス アカウントの権限を借用するには、その前に、そのサービス アカウントの権限借用を可能にする IAM ロールを持っている必要があります。プリンシパル自体が別のサービス アカウントである場合は、必要な権限をそのサービス アカウントに直接付与し、自身の権限を使用したほうが簡単に思われるかもしれません。しかし、自己権限借用というこの構成により、サービス アカウントが永続的に更新できるアクセス トークンが作成されるため、セキュリティの脆弱性が生じます。

サービス アカウントの権限借用には、常に 2 つのプリンシパルが関与する必要があります。つまり、呼び出し元を表すプリンシパルと、権限借用の対象となるサービス アカウント(権限保持サービス アカウント)です。

サービス アカウントの権限を借用して ID トークンを生成するには、次の一般的なプロセスを使用します。

手順については、ID トークンを作成するをご覧ください。

  1. 権限保持サービス アカウントにするサービス アカウントを作成または特定します。そのサービス アカウントに、対象のサービスに必要な IAM ロールを付与します。

    • Cloud Run サービスの場合、Cloud Run 起動元ロール(roles/run.invoker)を付与します。
    • Cloud Functions の場合、Cloud Functions 起動元ロール(roles/cloudfunctions.invoker)を付与します。
    • その他のターゲット サービスについては、サービスのプロダクト ドキュメントをご覧ください。
  2. 権限借用を行うプリンシパルを特定し、そのプリンシパルの認証情報を使用するようにアプリケーションのデフォルト認証情報(ADC)を設定します。

    開発環境では通常、gcloud CLI を使用して ADC に指定したユーザー アカウントがプリンシパルとなります。ただし、サービス アカウントが接続されているリソースで実行している場合は、接続されているサービス アカウントがプリンシパルになります。

  3. プリンシパルに、サービス アカウントの OpenID Connect ID トークン作成者ロール(roles/iam.serviceAccountOpenIdTokenCreator)を付与します。

  4. IAM Credentials API を使用して、承認されたサービス アカウントの ID トークンを生成します。

Cloud Run と Cloud Functions で開発用の汎用 ID トークンを生成する

gcloud CLI を使用して、呼び出し元に必要な IAM 権限が付与されている Cloud Run サービスまたは Cloud Functions で使用可能なユーザー認証情報の ID トークンを取得できます。このトークンは他のアプリケーションでは機能しません。

外部 ID プロバイダを使用して ID トークンを生成する

外部 ID プロバイダを使用して ID トークンを生成するには、Workload Identity 連携を使用します。これにより、Google Cloud と外部 ID プロバイダの間の関係を設定できます。その後、外部 ID プロバイダから提供される認証情報を使用して、Google Cloud で使用できる ID トークンまたはアクセス トークンを生成できます。

外部 ID プロバイダから提供される認証情報の ID トークンを生成するには、次の手順を行います。

  1. ターゲット サービスの呼び出しに必要な IAM ロールを付与するサービス アカウントを作成または特定します。

    この目的のために専用のサービス アカウントを作成し、必要なロールのみを付与することをおすすめします。このアプローチは、最小権限の原則に従うものです。

  2. ターゲット サービスを呼び出すために必要なロールを特定します。ターゲット サービスのサービス アカウントに次のロールを付与します。

    • Cloud Run サービスの場合、Cloud Run 起動元ロール(roles/run.invoker)を付与します。
    • Cloud Functions の場合、Cloud Functions 起動元ロール(roles/cloudfunctions.invoker)を付与します。
    • その他のターゲット サービスについては、サービスのプロダクト ドキュメントをご覧ください。
  3. Workload Identity 連携の構成の説明に従って ID プロバイダの Workload Identity 連携を構成します。

  4. サービス アカウントの権限借用を許可する権限を外部 ID に付与するの手順を行います。その際、権限を借用するサービス アカウントとして、前の手順で設定したサービス アカウントを使用します。

  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: トークンのオーディエンス(トークンを使用してアクセスされるアプリケーションやサービスなど)。

次のステップ