このドキュメントでは、IAP で保護されたリソースをユーザー アカウントまたはサービス アカウントから認証する方法について説明します。
プログラムによるアクセスとは、コマンドライン ツール、サービス間の呼び出し、モバイル アプリケーションなどのブラウザ以外のクライアントから IAP で保護されたアプリケーションを呼び出すことです。ユースケースに応じて、ユーザー認証情報またはサービス認証情報を使用して IAP の認証を行うことができます。
ユーザー アカウントは、個々のユーザーに属します。ユーザーの代わりにアプリケーションが IAP で保護されたリソースにアクセスする必要がある場合、ユーザー アカウントを認証します。詳しくは、ユーザー アカウントをご覧ください。
サービス アカウントは、個々のユーザーではなくアプリケーションを表します。アプリケーションから IAP で保護されたリソースにアクセスできるようにする場合、サービス アカウントを認証します。詳細については、サービス アカウントをご覧ください。
IAP は、プログラムによるアクセスに対して次のタイプの認証情報をサポートしています。
- OAuth 2.0 ID トークン - 対象クレームが IAP アプリケーションのリソース ID に設定された、人間ユーザーまたはサービス アカウント用の Google 発行のトークン。
- サービス アカウントの署名付き JWT - サービス アカウントの自己署名または Google 発行の JWT トークン。
これらの認証情報をリクエストの Authorization または Proxy-Authorization HTTP ヘッダーで IAP に含めます。
始める前に
始める前に、デベロッパー アカウント、サービス アカウント、モバイルアプリの認証情報を使用してプログラムで接続する IAP で保護されたアプリケーションがあることを確認してください。
ユーザー アカウントを認証する
デスクトップまたはモバイルアプリからアプリケーションへのユーザー アクセスを有効にすると、プログラムから IAP で保護されたリソースを操作できます。
モバイルアプリから認証する
- モバイルアプリ用の OAuth 2.0 クライアント ID を作成するか、既存の ID を使用します。既存の OAuth 2.0 クライアント ID を使用するには、OAuth クライアントを共有する方法の手順に沿って操作します。アプリケーションへのプログラムによるアクセスの許可リストに OAuth クライアント ID を追加します。
- IAP で保護されたリソースの OAuth 2.0 クライアント ID の ID トークンを取得します。
- Android: Google Sign-In API を使用して OpenID Connect(OIDC)トークンをリクエストします。
requestIdTokenクライアント ID を接続先のリソースのクライアント ID に設定します。 - iOS: Google ログインを使用して ID トークンを取得します。
- Android: Google Sign-In API を使用して OpenID Connect(OIDC)トークンをリクエストします。
Authorization: Bearerヘッダーに ID トークンを含めて、IAP で保護されたリソースに認証済みリクエストを送信します。
デスクトップ アプリから認証する
このセクションでは、デスクトップ コマンドラインからユーザー アカウントを認証する方法について説明します。
- デベロッパーがコマンドラインからアプリケーションにアクセスできるようにするには、デスクトップ OAuth 2.0 クライアント ID を作成するか、既存のデスクトップ OAuth クライアント ID を共有します。
- アプリケーションのプログラムによるアクセスの許可リストに OAuth ID を追加します。
アプリケーションにログインする
IAP で保護されたアプリにアクセスするには、各デベロッパーがログインする必要があります。gcloud CLI を使用するなどして、プロセスをスクリプトにパッケージ化できます。次の例では、curl を使用してログインし、アプリケーションにアクセスするために使用できるトークンを生成します。
- Google Cloud リソースにアクセスできるアカウントにログインします。
受信リクエストをエコーできるローカル サーバーを起動します。
# Example using Netcat (http://netcat.sourceforge.net/) nc -k -l 4444次の URI に移動します。ここで、
DESKTOP_CLIENT_IDはデスクトップ アプリのクライアント ID です。https://accounts.google.com/o/oauth2/v2/auth?client_id=DESKTOP_CLIENT_ID&response_type=code&scope=openid%20email&access_type=offline&redirect_uri=http://localhost:4444&cred_ref=trueローカル サーバーの出力で、リクエスト パラメータを探します。
GET /?code=CODE&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email&hd=google.com&prompt=consent HTTP/1.1コードの値をコピーして、次のコマンドの CODE を置き換えます。また、デスクトップ アプリのクライアント ID とシークレットも置き換えます。
curl --verbose \ --data client_id=DESKTOP_CLIENT_ID \ --data client_secret=DESKTOP_CLIENT_SECRET \ --data code=CODE \ --data redirect_uri=http://localhost:4444 \ --data grant_type=authorization_code \ https://oauth2.googleapis.com/tokenこのコマンドは、アプリケーションにアクセスするために使用できる
id_tokenフィールドを含む JSON オブジェクトを返します。
アプリケーションにアクセスする
アプリにアクセスするには、id_token を使用します。
curl --verbose --header 'Authorization: Bearer ID_TOKEN' URL 更新トークン
ログインフローで生成された更新トークンを使用して、新しい ID トークンを取得できます。これは、元の ID トークンが期限切れになった際に役立ちます。各 ID トークンは約 1 時間有効です。その間、特定のアプリに対して複数のリクエストを行うことができます。
次の例では、curl を使用して更新トークンを使用して新しい ID トークンを取得します。この例では、REFRESH_TOKEN はログインフローで生成したトークンです。DESKTOP_CLIENT_ID と DESKTOP_CLIENT_SECRET は、ログインフローで使用されているものと同じです。
curl --verbose \ --data client_id=DESKTOP_CLIENT_ID \ --data client_secret=DESKTOP_CLIENT_SECRET \ --data refresh_token=REFRESH_TOKEN \ --data grant_type=refresh_token \ https://oauth2.googleapis.com/token このコマンドは、アプリにアクセスするために使用できる新しい id_token フィールドを含む JSON オブジェクトを返します。
サービス アカウントを認証する
サービス アカウント JWT または OpenID Connect(OIDC)トークンを使用して、IAP で保護されたリソースに対してサービス アカウントを認証できます。次の表に、さまざまな認証トークンとその機能の違いを示します。
| 認証機能 | サービス アカウント JWT | OpenID Connect トークン |
|---|---|---|
| コンテキストアウェア アクセスのサポート | ||
| OAuth 2.0 クライアント ID の要件 | ||
| トークン スコープ | IAP で保護されたリソースの URL | OAuth 2.0 クライアント ID |
サービス アカウントの JWT で認証する
IAP は、Google ID、Identity Platform、Workforce Identity Federation で構成されたアプリケーションのサービス アカウント JWT 認証をサポートしています。
JWT を使用してサービス アカウントを認証するには、次の手順を行います。
呼び出し元のサービス アカウントにサービス アカウント トークン作成者ロール(
roles/iam.serviceAccountTokenCreator)を付与します。このロールにより、プリンシパルは JWT などの有効期間の短い認証情報を作成する権限が付与されます。
IAP で保護されたリソースの JWT を作成します。
サービス アカウントの秘密鍵を使用して JWT に署名します。
JWT を作成する
作成された JWT のペイロードは次の例のようになります。
{ "iss": SERVICE_ACCOUNT_EMAIL_ADDRESS, "sub": SERVICE_ACCOUNT_EMAIL_ADDRESS, "aud": TARGET_URL, "iat": IAT, "exp": EXP, } issフィールドとsubフィールドに、サービス アカウントのメールアドレスを指定します。メールアドレスは、サービス アカウントの JSON ファイルのclient_emailフィールドにあります。または、入力として指定されています。一般的な形式:service-account@PROJECT_ID.iam.gserviceaccount.comaudフィールドには、IAP で保護されたリソースの正確な URL またはパス ワイルドカード(/*)を含む URL(https://example.com/やhttps://example.com/*など)を指定します。audフィールドに正確な URL を含む JWT は、その特定の URL にのみアクセスできます。audフィールドにパス ワイルドカード(/*)を含む JWT は、末尾の*を含まないaud文字列で始まるすべての URL にアクセスできます。iatフィールドには現在の Unix エポック時間を指定し、expフィールドには 3,600 秒以内の時間を指定します。これは、JWT の有効期限を定義します。
JWT に署名する
JWT に署名するには、次のいずれかの方法を使用します。
- IAM 認証情報 API を使用して、秘密鍵に直接アクセスすることなく JWT に署名します。
- ローカル認証情報鍵ファイルを使用して、JWT にローカルで署名します。
IAM Service Account Credentials API を使用して JWT に署名する
IAM Service Account Credentials API を使用して、サービス アカウントの JWT に署名します。このメソッドは、サービス アカウントに関連付けられた秘密鍵を取得し、それを使用して JWT ペイロードに署名します。これにより、秘密鍵に直接アクセスせずに JWT に署名できます。
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
gcloud
- 次のコマンドを実行して、JWT ペイロードを含むリクエストを準備します。
cat > claim.json << EOM { "iss": "SERVICE_ACCOUNT_EMAIL_ADDRESS", "sub": "SERVICE_ACCOUNT_EMAIL_ADDRESS", "aud": "TARGET_URL", "iat": $(date +%s), "exp": $((`date +%s` + 3600)) } EOM - 次の Google Cloud CLI コマンドを使用して、
claim.jsonでペイロードに署名します。
gcloud iam service-accounts sign-jwt --iam-account="SERVICE_ACCOUNT_EMAIL_ADDRESS" claim.json output.jwt リクエストが成功すると、output.jwt には、IAP で保護されたリソースへのアクセスに使用できる署名付き JWT が含まれます。
Python
import datetime import json import google.auth from google.cloud import iam_credentials_v1 def generate_jwt_payload(service_account_email: str, resource_url: str) -> str: """Generates JWT payload for service account. Creates a properly formatted JWT payload with standard claims (iss, sub, aud, iat, exp) needed for IAP authentication. Args: service_account_email (str): Specifies the service account that the JWT is created for. resource_url (str): Specifies the scope of the JWT, the URL that the JWT will be allowed to access. Returns: str: JSON string containing the JWT payload with properly formatted claims. """ # Create current time and expiration time (1 hour later) in UTC iat = datetime.datetime.now(tz=datetime.timezone.utc) exp = iat + datetime.timedelta(seconds=3600) # Convert datetime objects to numeric timestamps (seconds since epoch) # as required by JWT standard (RFC 7519) payload = { "iss": service_account_email, "sub": service_account_email, "aud": resource_url, "iat": int(iat.timestamp()), "exp": int(exp.timestamp()), } return json.dumps(payload) def sign_jwt(target_sa: str, resource_url: str) -> str: """Signs JWT payload using ADC and IAM credentials API. Uses Google Cloud's IAM Credentials API to sign a JWT. This requires the caller to have iap.webServiceVersions.accessViaIap permission on the target service account. Args: target_sa (str): Service Account JWT is being created for. iap.webServiceVersions.accessViaIap permission is required. resource_url (str): Audience of the JWT and scope of the JWT token. This is the URL of the IAP-secured application. Returns: str: A signed JWT that can be used to access IAP-secured applications. Use in Authorization header as: 'Bearer <signed_jwt>' """ # Get default credentials from environment or application credentials source_credentials, project_id = google.auth.default() # Initialize IAM credentials client with source credentials iam_client = iam_credentials_v1.IAMCredentialsClient(credentials=source_credentials) # Generate the service account resource name. # Project should always be "-". # Replacing the wildcard character with a project ID is invalid. name = iam_client.service_account_path("-", target_sa) # Create and sign the JWT payload payload = generate_jwt_payload(target_sa, resource_url) # Sign the JWT using the IAM credentials API response = iam_client.sign_jwt(name=name, payload=payload) return response.signed_jwt curl
次のコマンドを実行して、JWT ペイロードを含むリクエストを準備します。
cat << EOF > request.json { "payload": JWT_PAYLOAD } EOFIAM を使用して JWT に署名する
Service Account Credentials API:
curl -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ -d @request.json \ "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL_ADDRESS:signJwt"リクエストが成功すると、署名付きの JWT がレスポンスで返されます。
JWT を使用して、IAP で保護されたリソースにアクセスします。
ローカルの認証情報鍵ファイルから JWT に署名する
JWT は、サービス アカウントの秘密鍵を使用して署名されます。
サービス アカウント キーファイルがある場合は、JWT にローカルで署名できます。
JWT にローカルで署名する場合は、ペイロードを含む JWT ヘッダーを含めます。ヘッダーの kid フィールドには、サービス アカウントの秘密鍵 ID を使用します。これは、サービス アカウント認証情報の JSON ファイルの private_key_id フィールドにあります。ファイル内の秘密鍵は、JWT の署名に使用されます。
アプリケーションにアクセスする
アプリケーションにアクセスするには、署名付き JWT を Authorization ヘッダーに含めます。
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL サービス アカウントの OIDC トークンで認証する
- OAuth 2.0 クライアント ID を作成するか、既存の ID を使用します。既存の OAuth 2.0 クライアント ID を使用するには、OAuth クライアントの共有方法の手順に沿って操作します。
- アプリケーションのプログラムによるアクセスの許可リストに OAuth ID を追加します。
- デフォルトのサービス アカウントが IAP で保護されたプロジェクトのアクセスリストに追加されていることを確認します。
IAP で保護されたリソースにリクエストを送信する場合は、Authorization ヘッダーにトークンを含める必要があります。Authorization: 'Bearer OIDC_TOKEN'
次のコードサンプルは、OIDC トークンを取得する方法を示しています。
デフォルトのサービス アカウント用に OIDC トークンを取得する
Compute Engine、App Engine、Cloud Run のデフォルトのサービス アカウント用 OIDC トークンを取得するには、次のコードサンプルを参照してアクセス トークンを生成し、IAP で保護されたリソースにアクセスします。
C#
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。
Go
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
Java
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
Node.js
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
PHP
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
Python
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
Ruby
IAP への認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。
ローカルのサービス アカウント キーファイルから OIDC トークンを取得する
サービス アカウント キーファイルを使用して OIDC トークンを生成するには、キーファイルを使用して JWT アサーションを作成して署名し、そのアサーションを ID トークンと交換します。次の Bash スクリプトは、このプロセスを示しています。
Bash
#!/usr/bin/env bash # # Example script that generates an OIDC token using a service account key file and uses it to access an IAP-secured resource. set -euo pipefail get_token() { # Get the bearer token in exchange for the service account credentials local service_account_key_file_path="${1}" local iap_client_id="${2}" # Define the scope and token endpoint local iam_scope="https://www.googleapis.com/auth/iam" local oauth_token_uri="https://www.googleapis.com/oauth2/v4/token" # Extract data from service account key file local private_key_id="$(cat "${service_account_key_file_path}" | jq -r '.private_key_id')" local client_email="$(cat "${service_account_key_file_path}" | jq -r '.client_email')" local private_key="$(cat "${service_account_key_file_path}" | jq -r '.private_key')" # Set token timestamps (current time and expiration 10 minutes later) local issued_at="$(date +%s)" local expires_at="$((issued_at + 600))" # Create JWT header and payload local header="{'alg':'RS256','typ':'JWT','kid':'${private_key_id}'}" local header_base64="$(echo "${header}" | base64 | tr -d '\n')" local payload="{'iss':'${client_email}','aud':'${oauth_token_uri}','exp':${expires_at},'iat':${issued_at},'sub':'${client_email}','target_audience':'${iap_client_id}'}" local payload_base64="$(echo "${payload}" | base64 | tr -d '\n')" # Create JWT signature using the private key local signature_base64="$(printf %s "${header_base64}.${payload_base64}" | openssl dgst -binary -sha256 -sign <(printf '%s\n' "${private_key}") | base64 | tr -d '\n')" local assertion="${header_base64}.${payload_base64}.${signature_base64}" # Exchange the signed JWT assertion for an ID token local token_payload="$(curl -s \ --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \ --data-urlencode "assertion=${assertion}" \ https://www.googleapis.com/oauth2/v4/token)" # Extract just the ID token from the response local bearer_id_token="$(echo "${token_payload}" | jq -r '.id_token')" echo "${bearer_id_token}" } main() { # Check if required arguments are provided if [[ $# -lt 3 ]]; then echo "Usage: $0 <service_account_key_file.json> <iap_client_id> <url>" exit 1 fi # Assign parameters to variables SERVICE_ACCOUNT_KEY="$1" IAP_CLIENT_ID="$2" URL="$3" # Generate the ID token echo "Generating token..." ID_TOKEN=$(get_token "${SERVICE_ACCOUNT_KEY}" "${IAP_CLIENT_ID}") # Access the IAP-secured resource with the token echo "Accessing: ${URL}" curl --header "Authorization: Bearer ${ID_TOKEN}" "${URL}" } # Run the main function with all provided arguments main "$@" このスクリプトは次の手順を実行します。
- JSON キーファイルからサービス アカウント キー情報を抽出します。
- ターゲット オーディエンスとして IAP クライアント ID を含む、必要なフィールドを含む JWT を作成します。
- サービス アカウントの秘密鍵を使用して JWT に署名します。
- Google の OAuth サービスを介してこの JWT を OIDC トークンと交換します。
- 結果のトークンを使用して、IAP で保護されたリソースに認証済みリクエストを送信します。
このスクリプトを使用するには:
- ファイルに保存します(例:
get_iap_token.sh)。 - 実行可能にする:
chmod +x get_iap_token.sh - 次の 3 つのパラメータを指定して実行します。
./get_iap_token.sh service-account-key.json \ OAUTH_CLIENT_ID \ URL ここで
service-account-key.jsonは、ダウンロードしたサービス アカウント キーファイルです。- OAUTH_CLIENT_ID は、IAP で保護されたリソースの OAuth クライアント ID です。
- URL はアクセスする URL です。
サービス アカウントの権限借用を使用して OIDC トークンを取得する
上記以外の場合は、IAP で保護されたリソースにアクセスする直前に IAM 認証情報 API を使用し、ターゲット サービス アカウントになりすまして OIDC トークンを生成します。このプロセスには、次のステップが含まれます。
呼び出し側のサービス アカウント(ID トークンを取得するコードに関連付けられたサービス アカウント)に、サービス アカウントの OpenID Connect ID トークン作成者ロール(
roles/iam.serviceAccountOpenIdTokenCreator)を付与します。これにより、呼び出し元のサービス アカウントが、ターゲット サービス アカウントの権限を借用できるようになります。
呼び出し側のサービス アカウントが提供する認証情報を使用して、ターゲット サービス アカウントの generateIdToken メソッドを呼び出します。
audienceフィールドにクライアント ID を設定します。
手順については、ID トークンを作成するをご覧ください。
Proxy-Authorization ヘッダーからの認証
アプリケーションが Authorization リクエスト ヘッダーを使用する場合は、代わりに Proxy-Authorization: Bearer ヘッダーに ID トークンを含めることができます。有効な ID トークンが Proxy-Authorization ヘッダーで見つかった場合、IAP はそのトークンを使用してリクエストを承認します。リクエストを承認すると、IAP はコンテンツを処理せずに Authorization ヘッダーをアプリケーションに渡します。
Proxy-Authorization ヘッダーに有効な ID トークンが見つからない場合、IAP は Authorization ヘッダーの処理を続行し、Proxy-Authorization ヘッダーを削除してから、リクエストをアプリケーションに渡します。
次のステップ
- Authorization: Bearer トークンの詳細を確認する。
- Android 用のログインまたは iOS 用のログインを試す。