このページでは、Identity-Aware Proxy(IAP)で保護されたリソースをユーザー アカウントまたはサービス アカウントから認証する方法について説明します。
プログラムによるアクセスは、ブラウザ以外のクライアントから IAP で保護されたアプリケーションを呼び出すシナリオです。これには、コマンドライン ツール、サービス間呼び出し、モバイル アプリケーションが含まれます。ユースケースに応じて、ユーザー認証情報またはサービス認証情報を使用して IAP の認証を行う場合があります。
ユーザー アカウントは、個々のユーザーに属します。ユーザーの代わりにアプリケーションが IAP で保護されたリソースにアクセスする必要がある場合、ユーザー アカウントを認証します。詳しくは、ユーザー アカウントをご覧ください。
サービス アカウントは、個々のユーザーではなくアプリケーションを表します。アプリケーションから IAP で保護されたリソースにアクセスできるようにする場合、サービス アカウントを認証します。詳細については、サービス アカウントをご覧ください。
IAP は、プログラマティック アクセス用の次のタイプの認証情報をサポートしています。
- OAuth 2.0 ID トークン - 人間のユーザーまたはサービス アカウント用の Google 発行トークン。対象クレームが IAP アプリケーションのリソース ID に設定されています。
- サービス アカウントで署名された JWT - サービス アカウントの自己署名または Google 発行の JWT トークン。
これらの認証情報を Authorization
または Proxy-Authorization
HTTP ヘッダーで IAP に渡します。
始める前に
始める前に、デベロッパー アカウント、サービス アカウント、モバイルアプリの認証情報を使用してプログラムで接続する、IAP で保護されたアプリケーションが必要です。
ユーザー アカウントを認証する
デスクトップまたはモバイルアプリからアプリへのユーザー アクセスを有効にすると、プログラムから IAP で保護されたリソースを操作できます。
モバイルアプリから認証する
- モバイルアプリ用に OAuth 2.0 クライアント ID を作成するか、既存の OAuth 2.0 クライアント ID を使用します。既存の OAuth 2.0 クライアント ID を使用するには、OAuth クライアントを共有する方法の手順に沿って操作してください。アプリケーションのプログラムによるアクセス用に、OAuth クライアント ID を許可リストに追加します。
- IAP で保護されたクライアント 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 値をコピーし、次のコマンドの
AUTH_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.com
aud
フィールドには、IAP で保護されたリソースの 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
に署名付き JWT が含まれ、IAP で保護されたリソースへのアクセスに使用できます。
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 service account JWT is created for.
resource_url (str): Specifies 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 protected application.
Returns:
str: A signed JWT that can be used to access IAP protected apps.
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
# If project_id is None, use '-' as placeholder as per API requirements
project = project_id if project_id else "-"
name = iam_client.service_account_path(project, 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 } EOF
IAM を使用して 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 ヘッダーを送信します。ヘッダーの kid
フィールドには、サービス アカウントの秘密鍵 ID を使用します。これは、サービス アカウント認証情報 JSON ファイルの private_key_id
フィールドにあります。この鍵は JWT の署名にも使用されます。
アプリケーションへのアクセス
いずれの場合も、アプリにアクセスするには signed-jwt
を使用します。
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
OIDC トークンによる認証
- 既存の OAuth 2.0 クライアント 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 用のログインを試す。