Azure 工作負載透過出示由 Microsoft Entra ID 簽發的「JSON Web Token」(JSON 網路權杖),即 JWT,來向 Claude API 進行驗證,然後將其交換為短期有效的 Anthropic 存取權杖。取得 Entra 簽發權杖的常見方式有兩種:
http://169.254.169.254/metadata/identity/oauth2/token 的 Azure Instance Metadata Service (IMDS),並接收其所指派識別的 JWT。AZURE_FEDERATED_TOKEN_FILE 所指定的路徑。工作負載在 Entra 端交換該權杖,以取得 Entra 簽發的存取權杖。在這兩種情況下,您向 Anthropic 出示的 Entra 簽發權杖都帶有租用戶專屬的 Entra 簽發者(下方的設定 Anthropic 步驟會顯示需註冊的確切 URL),以及 sub 和 oid 宣告中的受控識別物件 ID。您只需向 Anthropic 註冊該簽發者一次,撰寫一條符合預期宣告的聯合規則,您的工作負載即可在執行階段將其 Entra 權杖交換為 sk-ant-oat01-... 存取權杖。
AKS Pod 也可以選擇跳過 Entra 交換步驟,直接向 Anthropic 出示 Kubernetes 投射的服務帳戶權杖。該路徑會向 Anthropic 註冊您的 AKS 叢集 OIDC 簽發者,而非您的 Entra 租用戶。該流程請參閱 Kubernetes。
設定 Azure 將為其簽發權杖的識別。請選擇與您工作負載執行位置相符的路徑。
受控識別的 Entra 簽發權杖帶有以下宣告:
{
"iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"sub": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"aud": "https://api.anthropic.com",
"oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
"tid": "<TENANT_ID>",
"azp": "<CLIENT_ID>",
"exp": 1775527120
}sub 和 oid 相同(即受控識別的物件 ID)。azp 是應用程式或用戶端 ID。比對 oid 可授權一個特定的識別,或比對 azp 可授權與某個應用程式註冊相關聯的任何識別。tid 宣告會重複您的租用戶 ID;對其進行比對屬於深度防禦,因為簽發者 URL 已經固定了租用戶。
依照設定逐步說明在 Claude Console 中註冊聯合簽發者、建立 Anthropic 服務帳戶,以及建立聯合規則。在 Console 中,選擇 OIDC 提供者選項,並提供以下 Entra 專屬的值。
聯合簽發者: Entra 在每個租用戶的簽發者 URL 上發布 OIDC 探索文件,因此請使用探索模式。您聯合的每個 Azure 租用戶都需要自己的簽發者記錄。
{
"name": "azure-prod-tenant",
"issuer_url": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"jwks_source": "discovery"
}根據權杖版本的不同,iss 宣告可能會是 https://sts.windows.net/<TENANT_ID>/。請解碼您的受控識別權杖(下方的「驗證」章節會說明方法),並註冊其中包含的 iss 值。這兩個 URL 共用相同的 JWKS,因此探索模式對兩者皆適用。
聯合規則: 比對受控識別的物件 ID 和您的租用戶 ID。
{
"name": "azure-inference-worker",
"issuer_id": "fdis_...",
"match": {
"audience": "https://api.anthropic.com",
"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
}在執行階段,您的工作負載會擷取其 Entra 權杖,在 POST /v1/oauth/token 進行交換,並使用傳回的 bearer 權杖來呼叫 Claude。當您提供權杖提供者可呼叫物件時,每個 Anthropic SDK 都會處理交換和重新整理迴圈,如以下範例所示。cURL 分頁顯示原始流程。
在 AKS 上,AZURE_FEDERATED_TOKEN_FILE 所指向的檔案是由您叢集的 OIDC 簽發者簽署的 Kubernetes 投射服務帳戶權杖,而非 Entra 簽發的權杖。若要維持本頁所述的 Entra 中介路徑,請先在 https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token(聯合 client_credentials 授權)交換該權杖,然後將產生的 Entra 存取權杖作為識別權杖傳遞給 Anthropic SDK。
或者,直接向 Anthropic 註冊您的 AKS 叢集 OIDC 簽發者,並跳過 Entra 這一步。該模式請參閱 Kubernetes。
從您的 Azure 資源執行前面所示的 cURL 交換,並確認 POST /v1/oauth/token 傳回 200,其中包含以 sk-ant-oat01- 開頭的 access_token 以及以秒為單位的 expires_in 值。若出現 400 invalid_grant,請參閱疑難排解失敗的交換;Azure 端最常見的原因是您註冊的 issuer_url 與解碼後權杖中的 iss 宣告不符。兩者必須完全相符。對於受控識別權杖,iss 值為 https://login.microsoftonline.com/<TENANT_ID>/v2.0 或 https://sts.windows.net/<TENANT_ID>/。
oid 宣告是受控識別的 GUID,沒有穩定的前綴。帶有 * 的
subject_prefix 會比對租用戶中的任意識別,因此任何持有受控識別的
工作負載都可能取得聯合的 Anthropic 權杖。
將規則的 match 區塊鎖定在符合您使用案例的最窄範圍:
oid 作為精確值進行比對: 將 claims.oid 設定為受控識別的完整物件 ID,且絕不對 Azure 權杖使用 subject_prefix。tid 作為深度防禦: 簽發者 URL 已經固定了您的租用戶,但加入 claims.tid 可在日後簽發者記錄被編輯時防範設定偏移。audience 設定為 https://api.anthropic.com,以拒絕為其他資源鑄造的權杖。Was this page helpful?
import os
import anthropic
import requests
from anthropic import WorkloadIdentityCredentials
IMDS_URL = "http://169.254.169.254/metadata/identity/oauth2/token"
def fetch_entra_token() -> str:
"""Fetch a managed identity token from Azure IMDS."""
response = requests.get(
IMDS_URL,
headers={"Metadata": "true"},
params={"api-version": "2018-02-01", "resource": "https://api.anthropic.com"},
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-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from Azure"}],
)
print(message.content[0].text)import os
from pathlib import Path
import httpx
import anthropic
from anthropic import WorkloadIdentityCredentials
def fetch_entra_token_via_federation() -> str:
federated_token = Path(os.environ["AZURE_FEDERATED_TOKEN_FILE"]).read_text()
response = httpx.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": "https://api.anthropic.com/.default",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": federated_token,
},
)
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-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello from Azure"}],
)
print(message.content[0].text)