Azure 工作負載透過出示由 Microsoft Entra ID 簽發的 JSON Web Token(JWT)向 Claude API 進行驗證,然後將其交換為短效的 Anthropic 存取權杖。在每個 Azure 平台上,設定都遵循相同的模式:
POST /v1/oauth/token 將其 Entra 簽發的權杖交換為 sk-ant-oat01-... Anthropic 存取權杖,並使用它呼叫 Claude。在這兩種路徑上,您出示給 Anthropic 的權杖都在 sub 和 oid 宣告中攜帶您租用戶專屬的 Entra 簽發者和受控識別的物件 ID;唯一的差異在於工作負載取得該權杖的方式。請根據您的工作負載執行位置選擇對應章節:VM、VM Scale Sets、App Service、Functions 或 Container Apps 請參閱使用受控識別;AKS 請參閱在 AKS 上使用 Entra Workload Identity。
只有當請求的受眾以具有服務主體的應用程式註冊形式存在於您的租用戶中時,Microsoft Entra ID 才會簽發權杖。建立一個應用程式註冊來代表 Claude API 受眾;租用戶中的每個工作負載都可以為它請求權杖。若沒有此註冊,權杖請求會失敗並出現「resource not found in tenant」錯誤(受控識別端點回傳 AADSTS50001,Entra 權杖端點回傳 AADSTS500011)。
# 建立代表 Claude API 受眾的應用程式註冊。
APP_ID=$(az ad app create --display-name claude-api-federation --query appId -o tsv)
# 要求 v2.0 存取權杖並設定 api://<APP_ID> 識別碼 URI。
az ad app update --id "$APP_ID" \
--identifier-uris "api://$APP_ID" \
--set api.requestedAccessTokenVersion=2
# 建立服務主體,讓受眾能在您的租用戶中解析。
az ad sp create --id "$APP_ID"當您的工作負載在 VM、VM Scale Set、App Service、Functions 或 Container Apps 上執行時,請使用此路徑。工作負載從平台的本機權杖端點為其指派的受控識別請求 Entra 簽發的 JWT,然後將該 JWT 與 Anthropic 進行交換。
附加受控識別
在您的 Azure 資源上啟用系統指派或使用者指派的受控識別。在 Azure 入口網站中,開啟該資源,前往身分識別,並開啟系統指派(或附加使用者指派的身分識別)。
建立身分識別後,記下其物件(主體)ID。此 GUID 會同時作為簽發權杖中的 sub 和 oid 宣告出現,而您的 Anthropic 聯合規則將以它進行比對。您可以在資源的身分識別頁面上找到它;對於使用者指派的身分識別,它是受控識別資源概觀頁面上的物件(主體)ID。(受控識別在 Microsoft Entra ID 中只有服務主體,沒有應用程式註冊。)
找到平台的權杖端點
一旦附加身分識別後,平台會公開一個本機權杖端點:
http://169.254.169.254/metadata/identity/oauth2/token,需帶上標頭 Metadata: true 和 api-version=2018-02-01。IDENTITY_ENDPOINT 環境變數中的 URL,並將標頭 X-IDENTITY-HEADER 設為 IDENTITY_HEADER 的值,以及 api-version=2019-08-01。這些平台上無法存取 IMDS。如果資源有多個使用者指派的受控識別,請在權杖請求中加入 client_id=<IDENTITY_CLIENT_ID> 以選擇其中一個。Azure 建議一律指定它。若未指定,結果取決於該資源是否也啟用了系統指派的身分識別:如果有,請求會靜默地回退到該身分識別,然後無法通過您聯合規則的 oid 比對;如果沒有,一旦附加第二個使用者指派的身分識別,請求就會直接失敗。
解碼範例權杖
從端點請求權杖並解碼其酬載,以確認您的聯合規則需要比對的宣告。(解碼指令請參閱疑難排解失敗的交換。)受控識別的 v2.0 權杖攜帶以下宣告:
{
"iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"sub": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"aud": "<APP_ID>",
"oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"tid": "<TENANT_ID>",
"azp": "<IDENTITY_CLIENT_ID>",
"ver": "2.0",
"exp": 1775527120
}| 宣告 | 值 | 在以下情況比對 |
|---|---|---|
oid | 受控識別的物件 ID,與 sub 相同 | 您想要授權一個特定的受控識別。這是預設做法;設定 Anthropic 中的規則會比對它。 |
azp | 呼叫端身分識別的用戶端 ID | 您想要授權共用同一個應用程式註冊的所有工作負載。對於受控識別,azp 是該身分識別所獨有的,因此等同於 oid。 |
aud | 受眾應用程式註冊的用戶端 ID(來自註冊權杖受眾的 <APP_ID> GUID) | 一律比對。規則的 audience 欄位必須與權杖的 aud 值完全相等。 |
tid | 您的租用戶 ID | 您想要深度防禦。簽發者 URL 已經固定了租用戶。 |
如果解碼後權杖的 ver 宣告為 1.0,宣告名稱和值會有所不同。請在繼續之前參閱如果您的權杖是 v1.0。
在 Claude Console 中,開啟 Settings → Workload identity,點擊 Connect workload,然後選擇 Microsoft Entra 圖磚。精靈會引導您完成註冊簽發者、建立服務帳戶和建立聯合規則。
精靈會為您建立這些資源。無論您是在精靈中輸入這些值,還是將其傳送至 Admin API,請使用以下值:
聯合簽發者: 在精靈的 Token issuer 選擇器中選擇 v2.0 (login.microsoftonline.com)。(選擇器預設為 v1;該預設值是為了那些重複使用仍發出 v1.0 權杖的舊註冊的租用戶而存在。)Entra 在每個租用戶的簽發者 URL 上發布 OIDC 探索文件,因此請使用探索模式。您聯合的每個 Microsoft Entra 租用戶都需要自己的簽發者記錄。
{
"name": "azure-prod-tenant",
"issuer_url": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"jwks": { "type": "discovery" },
"max_jwt_lifetime_seconds": 86400
}較長的可接受存留期意味著外洩的 Entra 權杖可被交換的時間更長。如果權杖外洩,應對手段是停用聯合規則;嚴格的 oid 比對可從一開始就限制哪些身分識別可以交換權杖,如限縮規則範圍所述。
聯合規則: 以受控識別的物件 ID 和您的租用戶 ID 進行比對。對於本指南設定的 v2.0 權杖,audience 值是受眾應用程式註冊的用戶端 ID(來自註冊權杖受眾的 <APP_ID> GUID)。請使用您解碼後權杖中的確切 aud 值。
{
"name": "azure-inference-worker",
"issuer_id": "fdis_...",
"match": {
"audience": "<APP_ID>",
"claims": {
"oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"tid": "<TENANT_ID>"
}
},
"target": {
"type": "service_account",
"service_account_id": "svac_..."
},
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}token_lifetime_seconds 是交換所回傳的 Anthropic 存取權杖的存留期,而非 Entra 權杖的存留期;SDK 會為您重新整理它。
在執行階段,您的工作負載會擷取其 Entra 權杖,在 POST /v1/oauth/token 進行交換,並使用回傳的 bearer 權杖呼叫 Claude。當您提供權杖提供者可呼叫物件(token-provider callable)時,每個 Anthropic SDK 都會處理交換和重新整理迴圈,如以下範例所示。cURL 分頁顯示原始流程。
範例從平台的權杖端點擷取受控識別權杖:VM 和 VM Scale Sets 上使用 IMDS,App Service、Functions 和 Container Apps 上使用 IDENTITY_ENDPOINT 服務。請將 api://<APP_ID> 資源值中的 <APP_ID> 替換為註冊權杖受眾中受眾應用程式註冊的用戶端 ID。
import os
import anthropic
import requests
from anthropic import WorkloadIdentityCredentials
# audience 應用程式註冊的識別碼 URI(請參閱「註冊權杖 audience」)。
AUDIENCE = "api://<APP_ID>"
def fetch_entra_token() -> str:
"""Fetch a managed identity token from the platform's token endpoint."""
# 若有多個使用者指派的身分識別,請將 client_id=<IDENTITY_CLIENT_ID>
# 加入請求參數中以選擇其中一個。
if endpoint := os.environ.get("IDENTITY_ENDPOINT"):
# App Service、Functions、Container Apps
response = requests.get(
endpoint,
headers={"X-IDENTITY-HEADER": os.environ["IDENTITY_HEADER"]},
params={"api-version": "2019-08-01", "resource": AUDIENCE},
timeout=5,
)
else:
# VM 或 VM Scale Set:Azure Instance Metadata Service(IMDS)
response = requests.get(
"http://169.254.169.254/metadata/identity/oauth2/token",
headers={"Metadata": "true"},
params={"api-version": "2018-02-01", "resource": AUDIENCE},
timeout=5,
)
response.raise_for_status()
return response.json()["access_token"]
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=fetch_entra_token,
federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
),
)
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from Azure"}],
)
print(next(block.text for block in message.content if block.type == "text"))從您的 Azure 資源執行取得並使用權杖中顯示的 cURL 交換,並確認 POST /v1/oauth/token 回傳 200,其中 access_token 以 sk-ant-oat01- 開頭,且 expires_in 值以秒為單位。若出現 400 invalid_grant,請解碼 Entra 權杖(指令請參閱疑難排解失敗的交換)並檢查最常見的 Azure 端原因:
issuer_url 必須與權杖的 iss 宣告完全相符。v2.0 權杖攜帶 https://login.microsoftonline.com/<TENANT_ID>/v2.0;如果解碼後的 ver 宣告為 1.0,請參閱如果您的權杖是 v1.0。iat 和 exp 之間最長可達 24 小時。如果簽發者仍使用精靈的 7500(或 1 小時預設值),請依照設定 Anthropic 所述將 max_jwt_lifetime_seconds 提高到 86400。audience 必須與權杖的 aud 完全相等:對於本指南設定的 v2.0 權杖,即受眾應用程式註冊的用戶端 ID。appid 中攜帶用戶端 ID,而非 azp;請參閱如果您的權杖是 v1.0。當您的工作負載在 AKS pod 中執行時,請使用此路徑。Entra Workload Identity 將 Kubernetes 服務帳戶與使用者指派的受控識別聯合:Kubernetes 將服務帳戶權杖(由 AKS 叢集的 OIDC 簽發者簽署)投射到 pod 中 AZURE_FEDERATED_TOKEN_FILE 所指的路徑。該投射權杖不是 Entra 簽發的權杖,因此為了維持本頁所述的 Entra 中介路徑,工作負載會執行兩段式交換:首先在 https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token 以聯合 client_credentials 授與兌換投射權杖,取得 Entra 簽發的存取權杖,然後將該 Entra 權杖作為身分識別權杖傳遞給 Anthropic SDK。
在您的叢集上啟用 OIDC 簽發者和工作負載身分識別
啟用工作負載身分識別會為您安裝 azure-workload-identity mutating webhook;只有在非 AKS 叢集上才需要手動部署。請擷取叢集的 OIDC 簽發者 URL,供您在後續步驟中建立的聯合認證使用。
az aks update \
--resource-group <RESOURCE_GROUP> \
--name <CLUSTER_NAME> \
--enable-oidc-issuer \
--enable-workload-identity
AKS_OIDC_ISSUER=$(az aks show \
--resource-group <RESOURCE_GROUP> \
--name <CLUSTER_NAME> \
--query oidcIssuerProfile.issuerUrl -o tsv)建立使用者指派的受控識別
從身分識別擷取兩個值:用戶端 ID 會放入服務帳戶註解中(並以 AZURE_CLIENT_ID 注入到 pod 中),而物件(主體)ID 會作為您的 Anthropic 聯合規則所比對的 oid 宣告出現。
az identity create \
--resource-group <RESOURCE_GROUP> \
--name claude-inference-identity \
--location <LOCATION>
# 放在服務帳戶的 annotation 中;會以 AZURE_CLIENT_ID 注入到 pod。
IDENTITY_CLIENT_ID=$(az identity show \
--resource-group <RESOURCE_GROUP> \
--name claude-inference-identity \
--query clientId -o tsv)
# 會顯示為 oid 宣告,供您的同盟規則比對。
IDENTITY_OBJECT_ID=$(az identity show \
--resource-group <RESOURCE_GROUP> \
--name claude-inference-identity \
--query principalId -o tsv)建立帶有註解的 Kubernetes 服務帳戶
azure-workload-identity webhook 會讀取 azure.workload.identity/client-id 註解,將 AZURE_CLIENT_ID 注入到 pod 中,取得並使用權杖中的範例會從環境中讀取它。
apiVersion: v1
kind: ServiceAccount
metadata:
name: claude-inference
namespace: inference
annotations:
azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>在受控識別上建立聯合認證
聯合認證會信任您叢集的 OIDC 簽發者對該特定服務帳戶的簽發。--audience api://AzureADTokenExchange 值是 Entra 對傳入 Kubernetes 服務帳戶權杖的固定受眾;它與您先前註冊的 Claude API 受眾無關。
az identity federated-credential create \
--resource-group <RESOURCE_GROUP> \
--identity-name claude-inference-identity \
--name claude-inference-aks \
--issuer "$AKS_OIDC_ISSUER" \
--subject system:serviceaccount:inference:claude-inference \
--audience api://AzureADTokenExchange為 pod 加上標籤並設定其服務帳戶
pod 必須帶有 azure.workload.identity/use: "true" 標籤,並以帶有註解的服務帳戶執行。接著 webhook 會將 AZURE_FEDERATED_TOKEN_FILE、AZURE_CLIENT_ID 和 AZURE_TENANT_ID 注入到 pod 中。位於 AZURE_FEDERATED_TOKEN_FILE 的檔案包含由 AKS 叢集的 OIDC 簽發者簽署的 Kubernetes 投射服務帳戶權杖。
apiVersion: v1
kind: Pod
metadata:
name: inference-worker
namespace: inference
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: claude-inference
containers:
- name: app
image: your-registry/inference-worker:latest解碼範例權杖
您的 Anthropic 聯合規則看到的權杖不是投射的檔案;而是 client_credentials 交換回傳的 Entra 簽發權杖。從帶有標籤的 pod 內部,執行取得並使用權杖中 cURL 範例的步驟 1 並解碼結果。它攜帶與受控識別路徑相同的宣告結構:
{
"iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"sub": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"aud": "<APP_ID>",
"oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"tid": "<TENANT_ID>",
"azp": "<IDENTITY_CLIENT_ID>",
"ver": "2.0",
"exp": 1775527120
}sub 和 oid 是受控識別的物件 ID,aud 是受眾應用程式註冊的用戶端 ID,而 azp 是受控識別的用戶端 ID(即 AZURE_CLIENT_ID 的值)。存留期與受控識別路徑不同:client_credentials 權杖在 iat 和 exp 之間預設為隨機的 60 到 90 分鐘範圍,而非 24 小時。
在 Claude Console 中,開啟 Settings → Workload identity,點擊 Connect workload,然後選擇 Microsoft Entra 圖磚。精靈會引導您完成註冊簽發者、建立服務帳戶和建立聯合規則。
精靈會為您建立這些資源。無論您是在精靈中輸入這些值,還是將其傳送至 Admin API,請使用以下值:
聯合簽發者: 在精靈的 Token issuer 選擇器中選擇 v2.0 (login.microsoftonline.com)。(選擇器預設為 v1;該預設值是為了那些重複使用仍發出 v1.0 權杖的舊註冊的租用戶而存在。)Entra 在每個租用戶的簽發者 URL 上發布 OIDC 探索文件,因此請使用探索模式。您聯合的每個 Microsoft Entra 租用戶都需要自己的簽發者記錄。
{
"name": "azure-prod-tenant",
"issuer_url": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"jwks": { "type": "discovery" },
"max_jwt_lifetime_seconds": 7500
}較長的可接受存留期意味著外洩的 Entra 權杖可被交換的時間更長。如果權杖外洩,應對手段是停用聯合規則;嚴格的 oid 比對可從一開始就限制哪些身分識別可以交換權杖,如限縮規則範圍所述。
聯合規則: 以受控識別的物件 ID 和您的租用戶 ID 進行比對。對於本指南設定的 v2.0 權杖,audience 值是受眾應用程式註冊的用戶端 ID(來自註冊權杖受眾的 <APP_ID> GUID)。請使用您解碼後權杖中的確切 aud 值。
{
"name": "azure-inference-worker",
"issuer_id": "fdis_...",
"match": {
"audience": "<APP_ID>",
"claims": {
"oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"tid": "<TENANT_ID>"
}
},
"target": {
"type": "service_account",
"service_account_id": "svac_..."
},
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}token_lifetime_seconds 是交換所回傳的 Anthropic 存取權杖的存留期,而非 Entra 權杖的存留期;SDK 會為您重新整理它。
在執行階段,pod 會執行兩段式交換:它將 Kubernetes 投射的權杖(位於 AZURE_FEDERATED_TOKEN_FILE 的檔案)作為聯合 client_credentials 斷言傳送到 Entra 的權杖端點,然後在 POST /v1/oauth/token 交換所得的 Entra 存取權杖。當您將 Entra 擷取作為權杖提供者可呼叫物件提供時,每個 Anthropic SDK 都會處理第二次交換和重新整理迴圈,如以下範例所示。cURL 分頁顯示原始流程。
範例中出現兩個不同的用戶端 ID。<APP_ID> 是來自註冊權杖受眾的受眾應用程式註冊的用戶端 ID;範圍 api://<APP_ID>/.default 會向 Entra 請求一個以該受眾為目標的權杖。$AZURE_CLIENT_ID 是受控識別的用戶端 ID,由 webhook 注入,用於識別呼叫者。請勿將兩者互相替換。
import os
from pathlib import Path
import anthropic
import requests
from anthropic import WorkloadIdentityCredentials
def fetch_entra_token_via_federation() -> str:
federated_token = Path(os.environ["AZURE_FEDERATED_TOKEN_FILE"]).read_text()
response = requests.post(
f"https://login.microsoftonline.com/{os.environ['AZURE_TENANT_ID']}/oauth2/v2.0/token",
data={
"client_id": os.environ["AZURE_CLIENT_ID"],
"grant_type": "client_credentials",
"scope": "api://<APP_ID>/.default",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": federated_token,
},
timeout=5,
)
response.raise_for_status()
return response.json()["access_token"]
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=fetch_entra_token_via_federation,
federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
),
)
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from Azure"}],
)
print(next(block.text for block in message.content if block.type == "text"))從帶有標籤的 pod 內部,執行取得並使用權杖中顯示的 cURL 交換,並確認 POST /v1/oauth/token 回傳 200,其中 access_token 以 sk-ant-oat01- 開頭,且 expires_in 值以秒為單位。若出現 400 invalid_grant,請解碼步驟 1 中 Entra 簽發的權杖(指令請參閱疑難排解失敗的交換)並檢查最常見的 Azure 端原因:
issuer_url 必須與權杖的 iss 宣告完全相符。v2.0 權杖攜帶 https://login.microsoftonline.com/<TENANT_ID>/v2.0;如果解碼後的 ver 宣告為 1.0,請參閱如果您的權杖是 v1.0。client_credentials 權杖延長超過 7500 秒,請依照設定 Anthropic 所述提高簽發者的 max_jwt_lifetime_seconds。audience 必須與權杖的 aud 完全相等:對於本指南設定的 v2.0 權杖,即受眾應用程式註冊的用戶端 ID。appid 中攜帶用戶端 ID,而非 azp;請參閱如果您的權杖是 v1.0。本指南以 api.requestedAccessTokenVersion: 2 設定受眾應用程式註冊,因此它顯示的每個權杖都是 v2.0。如果您重複使用未設定 requestedAccessTokenVersion 的現有註冊,Entra 會改為簽發 v1.0 權杖。請解碼範例權杖並檢查其 ver 宣告;如果是 1.0,有四件事會改變:
iss 宣告是 https://sts.windows.net/<TENANT_ID>/,而非 https://login.microsoftonline.com/<TENANT_ID>/v2.0。請完全依照您權杖的 iss 宣告所攜帶的內容註冊簽發者 URL。這兩個 URL 共用相同的 JWKS,因此探索模式對兩者都適用。aud 宣告是您作為 resource 傳入的識別碼 URI(例如 api://<APP_ID>),而非註冊的用戶端 ID。請將聯合規則的 audience 設為您解碼後權杖中的確切 aud 值。appid 中,而非 azp。這兩個宣告永遠不會出現在同一個權杖中,因此比對 azp 的規則永遠無法通過 v1.0 權杖。oid、sub 和 tid 宣告在兩個版本中攜帶相同的值,因此本指南的其餘部分無需變更即可適用。
聯合規則除了(或取代)claims 對應之外,還可以使用 subject_prefix 比對權杖的主體;欄位如何組合請參閱規則比對語意。這些身分識別的 Entra sub 值是固定長度的標準 GUID,因此包含完整 36 字元物件 ID 的 subject_prefix 只會比對到該主體;這是 Entra 主體格式的特性,而非 subject_prefix 的一般特性。
將規則的 match 區塊鎖定到符合您使用案例的最窄範圍:
oid: 將 claims.oid 設為受控識別的完整物件 ID。設為該完整物件 ID 的 subject_prefix 是等效的(Console 精靈會同時設定兩者);切勿使用萬用字元或部分 GUID 的 subject_prefix,那會比對到超出您預期的身分識別。tid 作為深度防禦: 簽發者 URL 已經固定了您的租用戶,但加入 claims.tid 可防範簽發者記錄日後被編輯時的設定漂移。audience 設為您解碼後權杖中的確切 aud 值,以便拒絕為其他應用程式鑄造的權杖。Was this page helpful?