程式輔助存取是指從非瀏覽器用戶端 (例如指令列工具、服務對服務呼叫和行動應用程式) 呼叫受 IAP 保護的應用程式。視用途而定,您可能需要使用使用者憑證或服務憑證向 IAP 進行驗證。
「使用者帳戶」屬於個別使用者。如果應用程式需要代表使用者存取受 IAP 保護的資源,您必須驗證使用者帳戶。詳情請參閱「使用者帳戶」。
- 服務帳戶代表應用程式,而非個別使用者。如要允許應用程式存取受 IAP 保護的資源,請驗證服務帳戶。詳情請參閱「服務帳戶」。
IAP 支援下列類型的程式輔助存取憑證:
* OAuth 2.0 ID 權杖:Google 核發給人類使用者或服務帳戶的權杖,其目標對象宣告設為 IAP 應用程式的資源 ID。 * 服務帳戶簽署的 JWT:服務帳戶的自行簽署或 Google 核發 JWT 權杖。在要求的 Authorization 或 Proxy-Authorization HTTP 標頭中,加入這些 IAP 憑證。
事前準備
確認您有要使用開發人員帳戶、服務帳戶或行動應用程式憑證,以程式輔助方式存取的應用程式。
如要建立一或多個 OAuth 2.0 用戶端,請參閱「程式輔助存取」。
驗證使用者帳戶
您可以讓使用者透過電腦或行動應用程式存取應用程式,允許程式與受 IAP 保護的資源互動。
透過行動應用程式驗證
- 為行動應用程式建立或使用現有的 OAuth 2.0 用戶端 ID。如要使用現有的 OAuth 2.0 用戶端 ID,請按照「如何共用 OAuth 用戶端」中的步驟操作。將 OAuth 用戶端 ID 新增至許可清單,以便透過程式輔助方式存取應用程式。
- 取得受 IAP 保護資源的 OAuth 2.0 用戶端 ID 權杖。
- Android:使用 Google 登入 API 要求 OpenID Connect (OIDC) 權杖。將
requestIdToken用戶端 ID 設為要連線的資源用戶端 ID。 - iOS:使用 Google 登入取得 ID 權杖。
- Android:使用 Google 登入 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 值,並在下列指令中替換 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 權杖的有效時間約為一小時,期間您可以向特定應用程式提出多項要求。
以下範例使用 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
這個指令會傳回 JSON 物件,其中包含新的 id_token 欄位,可用於存取應用程式。
驗證服務帳戶
您可以使用服務帳戶 JWT 或 OpenID Connect (OIDC) 權杖,向受 IAP 保護的資源驗證服務帳戶。下表列出不同驗證權杖及其功能之間的差異。| 驗證功能 | 服務帳戶 JWT | OpenID Connect 權杖 |
|---|---|---|
| 情境感知存取權支援 | ||
| OAuth 2.0 用戶端 ID 規定 | ||
| 權杖範圍 | 受 IAP 保護的資源網址 | OAuth 2.0 用戶端 ID |
使用服務帳戶 JWT 進行驗證
IAP 支援服務帳戶 JWT 驗證,適用於 Google Identity、Identity Platform 和員工身分聯盟設定的應用程式。使用 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 保護資源的確切網址,或含有路徑萬用字元 (/*) 的網址,例如https://example.com/或https://example.com/*。如果 JWT 的aud欄位包含確切網址,則只能存取該特定網址。如果 JWT 的aud欄位含有路徑萬用字元 (/*),則可存取所有開頭為aud字串 (不含結尾的*) 的網址。在
iat欄位中指定目前的 Unix 紀元時間,並在exp欄位中指定 3600 秒內的時間。這會定義 JWT 的到期時間。
簽署 JWT
您可以使用下列任一方法簽署 JWT:
- 使用 IAM Credentials 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 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 } 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 時,請在酬載中加入 JWT 標頭。針對標頭中的 kid 欄位,請使用服務帳戶的私密金鑰 ID,該 ID 位於服務帳戶憑證 JSON 檔案的 private_key_id 欄位中。檔案中的私密金鑰會用於簽署 JWT。
存取應用程式
如要存取應用程式,請在授權標頭中加入已簽署的 JWT:
curl --verbose --header 'Authorization: Bearer SIGNED_JWT' URL
使用服務帳戶 OIDC 權杖進行驗證
如要使用服務帳戶 OIDC 權杖進行驗證,請按照下列步驟操作:
建立新的 OIDC 用戶端 ID,或使用現有 ID。
如要建立新的 OAuth 2.0 用戶端 ID,請按照下列步驟操作:
如果您尚未註冊應用程式,請務必先完成註冊,才能使用 Google Auth。
前往 Google Auth Platform 頁面。
如果未選取專案,系統會提示您建立專案。
按一下「Create Client」(建立用戶端)。
選取適當的申請類型,並輸入任何必要資訊。
填寫所選用戶端類型的必要資訊。如要建立用戶端,請按一下「Create」(建立)。
如要使用現有的 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 金鑰檔案擷取服務帳戶金鑰資訊
- 建立含有必要欄位的 JWT,包括將 IAP 用戶端 ID 設為目標對象
- 使用服務帳戶的私密金鑰簽署 JWT
- 透過 Google 的 OAuth 服務,將這個 JWT 換成 OIDC 權杖
- 使用產生的權杖,向受 IAP 保護的資源提出經過驗證的要求
如要使用這個指令碼,請按照下列步驟操作:
- 將其儲存至檔案,例如:
get_iap_token.sh - 將其設為可執行:
chmod +x get_iap_token.sh - 執行時請提供三個參數:
./get_iap_token.sh service-account-key.json \
OAUTH_CLIENT_ID \
URL
其中:
service-account-key.json是您下載的服務帳戶金鑰檔案- OAUTH_CLIENT_ID 是受 IAP 保護資源的 OAuth 用戶端 ID
- URL 是您要存取的網址
使用服務帳戶模擬功能取得 OIDC 權杖
在所有其他情況下,請使用 IAM Credentials API,在存取受 IAP 保護的資源之前,模擬目標服務帳戶來產生 OIDC 權杖。這項程序包含下列步驟:
將服務帳戶 OpenID Connect 身分權杖建立者角色 (
roles/iam.serviceAccountOpenIdTokenCreator) 授予呼叫服務帳戶 (與取得 ID 權杖的程式碼相關聯的服務帳戶)。這樣一來,呼叫服務帳戶就能模擬目標服務帳戶。
使用呼叫服務帳戶提供的憑證,在目標服務帳戶上呼叫 generateIdToken 方法。
將
audience欄位設為用戶端 ID。
如需逐步說明,請參閱「建立 ID 權杖」。
透過 Proxy-Authorization 標頭驗證
如果應用程式使用 Authorization 要求標頭,您可以改為在 Proxy-Authorization: Bearer 標頭中加入 ID 權杖。如果在 Proxy-Authorization 標頭中找到有效的 ID 權杖,IAP 會使用該權杖授權要求。授權要求後,IAP 會將 Authorization 標頭傳遞至應用程式,而不處理內容。
如果在 Proxy-Authorization 標頭中找不到有效的 ID 權杖,IAP 會繼續處理 Authorization 標頭,並在將要求傳遞至應用程式之前,先移除 Proxy-Authorization 標頭。
存取應用程式
如要使用 Proxy-Authorization 標頭存取應用程式,請執行下列指令:
curl --verbose --header 'Proxy-Authorization: Bearer SIGNED_JWT' URL
後續步驟
- 進一步瞭解授權:不記名權杖。
- 請改用 Android 版登入或 iOS 版登入。