Azure 워크로드는 Microsoft Entra ID가 발급한 JSON Web Token(JWT)을 제시한 다음, 이를 단기 Anthropic 액세스 토큰으로 교환하여 Claude API에 인증합니다. 설정은 모든 Azure 플랫폼에서 동일한 형태를 따릅니다:
POST /v1/oauth/token에서 sk-ant-oat01-... Anthropic 액세스 토큰으로 교환하고 이를 사용하여 Claude를 호출합니다.두 경로 모두에서 Anthropic에 제시하는 토큰은 테넌트별 Entra 발급자와 관리 ID의 객체 ID를 sub 및 oid 클레임에 담고 있으며, 워크로드가 해당 토큰을 얻는 방법만 다릅니다. 워크로드가 실행되는 위치에 맞는 섹션을 선택하세요: VM, VM Scale Set, App Service, Functions 또는 Container Apps의 경우 관리 ID 사용하기, AKS의 경우 AKS에서 Entra Workload Identity 사용하기를 참조하세요.
Microsoft Entra ID는 요청된 대상이 서비스 주체가 있는 앱 등록으로 테넌트에 존재할 때만 토큰을 발급합니다. Claude API 대상을 나타내는 앱 등록을 하나 생성하세요. 테넌트의 모든 워크로드가 이를 위한 토큰을 요청할 수 있습니다. 이 등록이 없으면 토큰 요청은 "resource not found in tenant" 오류(관리 ID 엔드포인트에서는 AADSTS50001, Entra 토큰 엔드포인트에서는 AADSTS500011)로 실패합니다.
# Claude API 대상(audience)을 나타내는 앱 등록을 생성합니다.
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
# 테넌트에서 대상(audience)이 확인되도록 서비스 주체를 생성합니다.
az ad sp create --id "$APP_ID"api://<APP_ID> 식별자 URI 형식을 사용하세요. Entra는 https:// 식별자 URI를 자체 테넌트의 검증된 도메인으로 제한하므로, https://api.anthropic.com과 같은 URI는 대부분의 테넌트에서 등록할 수 없습니다. api://<APP_ID>는 어디서나 허용됩니다. requestedAccessTokenVersion: 2를 사용하면 이 대상에 대한 토큰은 v2.0이며, 이 가이드는 이를 전제로 합니다. v1.0 토큰을 발급하는 기존 등록을 재사용하는 경우 토큰이 v1.0인 경우를 참조하세요.
워크로드가 VM, VM Scale Set, App Service, Functions 또는 Container Apps에서 실행되는 경우 이 경로를 사용하세요. 워크로드는 플랫폼의 로컬 토큰 엔드포인트에서 할당된 관리 ID에 대한 Entra 발급 JWT를 요청한 다음, 해당 JWT를 Anthropic과 교환합니다.
관리 ID 연결하기
Azure 리소스에서 시스템 할당 또는 사용자 할당 관리 ID를 활성화합니다. Azure 포털에서 리소스를 열고 Identity로 이동한 다음 System assigned를 켜거나 사용자 할당 ID를 연결합니다.
ID가 생성된 후 Object (principal) ID를 기록해 두세요. 이 GUID는 발급된 토큰의 sub 및 oid 클레임 모두에 나타나며, Anthropic 페더레이션 규칙이 이를 기준으로 매칭합니다. 리소스의 Identity 페이지에서 찾을 수 있으며, 사용자 할당 ID의 경우 관리 ID 리소스의 Overview 페이지에 있는 Object (principal) ID입니다. (관리 ID는 Microsoft Entra ID에 서비스 주체만 있고 앱 등록은 없습니다.)
플랫폼의 토큰 엔드포인트 찾기
ID가 연결되면 플랫폼은 로컬 토큰 엔드포인트를 노출합니다:
http://169.254.169.254/metadata/identity/oauth2/token의 IMDS에 Metadata: true 헤더와 api-version=2018-02-01을 사용합니다.IDENTITY_ENDPOINT 환경 변수의 URL에 IDENTITY_HEADER 값으로 설정된 X-IDENTITY-HEADER 헤더와 api-version=2019-08-01을 사용합니다. 이러한 플랫폼에서는 IMDS에 접근할 수 없습니다.리소스에 사용자 할당 관리 ID가 둘 이상 있는 경우, 토큰 요청에 client_id=<IDENTITY_CLIENT_ID>를 추가하여 하나를 선택합니다. Azure는 항상 이를 지정할 것을 권장합니다. 지정하지 않으면 결과는 리소스에 시스템 할당 ID도 활성화되어 있는지에 따라 달라집니다. 활성화되어 있으면 요청이 조용히 해당 ID로 대체된 후 페더레이션 규칙의 oid 매칭에 실패하고, 활성화되어 있지 않으면 두 번째 사용자 할당 ID가 연결되는 즉시 요청이 바로 실패합니다.
샘플 토큰 디코딩하기
엔드포인트에서 토큰을 요청하고 페이로드를 디코딩하여 페더레이션 규칙이 매칭해야 하는 클레임을 확인합니다. (디코딩 명령은 실패한 교환 문제 해결하기를 참조하세요.) 관리 ID에 대한 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의 객체 ID, sub와 동일 | 특정 관리 ID 하나를 승인하려는 경우. 이것이 기본값이며, Anthropic 구성하기의 규칙이 이를 매칭합니다. |
azp | 호출하는 ID의 클라이언트 ID | 하나의 앱 등록을 공유하는 모든 워크로드를 승인하려는 경우. 관리 ID의 경우 azp는 해당 ID에 고유하므로 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
}관리 ID 워크로드에는 max_jwt_lifetime_seconds: 86400이 필요합니다. Azure는 각 리소스의 토큰을 해당 기간 동안 캐시하고 조기 갱신을 강제할 방법을 제공하지 않기 때문에 iat와 exp 사이가 최대 24시간인 관리 ID 토큰을 발급하며, 발급자의 1시간 기본값은 이러한 토큰을 invalid_grant로 거부합니다. Connect workload 마법사의 Microsoft Entra 타일은 max_jwt_lifetime_seconds를 7500으로 설정하여 발급자를 생성하고 생성 중에 이를 변경할 필드를 제공하지 않으므로, 마법사를 완료한 다음 Settings → Workload identity → Issuers를 열고 발급자를 편집하여 값을 86400으로 올리세요. Admin API를 통해 발급자를 업데이트할 수도 있습니다.
허용되는 수명이 길수록 유출된 Entra 토큰이 더 오래 교환 가능한 상태로 유지됩니다. 토큰이 유출되면 페더레이션 규칙을 비활성화하는 것이 대응 수단이며, 규칙 범위 지정하기에 설명된 대로 엄격한 oid 매칭은 애초에 토큰을 교환할 수 있는 ID를 제한합니다.
페더레이션 규칙: 관리 ID의 객체 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에서 교환하고, 반환된 베어러 토큰을 사용하여 Claude를 호출합니다. 다음 예제에서 볼 수 있듯이 토큰 제공자 콜러블을 제공하면 각 Anthropic SDK가 교환 및 갱신 루프를 처리합니다. cURL 탭은 원시 흐름을 보여줍니다.
샘플은 플랫폼의 토큰 엔드포인트에서 관리 ID 토큰을 가져옵니다. VM 및 VM Scale Set에서는 IMDS, App Service, Functions, Container Apps에서는 IDENTITY_ENDPOINT 서비스입니다. api://<APP_ID> 리소스 값의 <APP_ID>를 토큰 대상 등록하기의 대상 앱 등록 클라이언트 ID로 바꾸세요.
워크로드가 이미 Azure Identity 클라이언트 라이브러리를 사용하는 경우, 토큰 엔드포인트를 직접 호출하는 대신 해당 라이브러리의 토큰 획득(api://<APP_ID>/.default 범위를 사용하는 DefaultAzureCredential)을 ID 토큰 제공자로 전달하세요. 라이브러리는 Entra Workload Identity를 사용하는 AKS를 포함한 모든 Azure 플랫폼에서 올바른 엔드포인트를 선택합니다.
import os
import anthropic
import requests
from anthropic import WorkloadIdentityCredentials
# 대상(audience) 앱 등록의 식별자 URI (토큰 대상 등록 참조).
AUDIENCE = "api://<APP_ID>"
def fetch_entra_token() -> str:
"""Fetch a managed identity token from the platform's token endpoint."""
# 사용자 할당 ID가 여러 개인 경우 요청 매개변수에 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이 sk-ant-oat01-로 시작하는 access_token과 초 단위의 expires_in 값을 포함한 200을 반환하는지 확인합니다. 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입니다.azp가 아닌 appid에 담습니다. 토큰이 v1.0인 경우를 참조하세요.워크로드가 AKS 파드에서 실행되는 경우 이 경로를 사용하세요. Entra Workload Identity는 Kubernetes 서비스 계정을 사용자 할당 관리 ID와 페더레이션합니다. Kubernetes는 AKS 클러스터의 OIDC 발급자가 서명한 서비스 계정 토큰을 AZURE_FEDERATED_TOKEN_FILE의 경로에 있는 파드에 프로젝션합니다. 이 프로젝션된 토큰은 Entra가 발급한 토큰이 아니므로, 이 페이지에서 설명하는 Entra 중개 경로를 유지하려면 워크로드가 2단계 교환을 수행합니다. 먼저 프로젝션된 토큰을 https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token에서 (페더레이션된 client_credentials 권한 부여로) Entra 발급 액세스 토큰으로 교환한 다음, 해당 Entra 토큰을 ID 토큰으로 Anthropic SDK에 전달합니다.
AKS 파드는 Entra 교환을 건너뛰고 Kubernetes가 프로젝션한 서비스 계정 토큰을 Anthropic에 직접 제시할 수도 있습니다. 이 경로는 Entra 테넌트 대신 AKS 클러스터의 OIDC 발급자를 Anthropic에 등록합니다. 해당 흐름은 Kubernetes와 함께 WIF 사용하기를 참조하세요.
클러스터에서 OIDC 발급자와 워크로드 ID 활성화하기
워크로드 ID를 활성화하면 azure-workload-identity 변형 웹훅이 자동으로 설치됩니다. 비 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 생성하기
ID에서 두 가지 값을 기록하세요. Client ID는 서비스 계정 주석에 들어가며(파드에 AZURE_CLIENT_ID로 주입됨), Object (principal) ID는 Anthropic 페더레이션 규칙이 매칭하는 oid 클레임으로 나타납니다.
az identity create \
--resource-group <RESOURCE_GROUP> \
--name claude-inference-identity \
--location <LOCATION>
# 서비스 계정 어노테이션에 들어가며, AZURE_CLIENT_ID로 파드에 주입됩니다.
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 웹훅은 azure.workload.identity/client-id 주석을 읽어 AZURE_CLIENT_ID를 파드에 주입하며, 토큰 획득 및 사용하기의 샘플은 이를 환경에서 읽습니다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: claude-inference
namespace: inference
annotations:
azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>관리 ID에 페더레이션 자격 증명 생성하기
페더레이션 자격 증명은 해당 특정 서비스 계정에 대해 클러스터의 OIDC 발급자를 신뢰합니다. --audience api://AzureADTokenExchange 값은 들어오는 Kubernetes 서비스 계정 토큰에 대한 Entra의 고정 대상이며, 앞서 등록한 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파드에 레이블을 지정하고 서비스 계정 설정하기
파드는 azure.workload.identity/use: "true" 레이블을 가지고 주석이 달린 서비스 계정으로 실행되어야 합니다. 그러면 웹훅이 AZURE_FEDERATED_TOKEN_FILE, AZURE_CLIENT_ID, AZURE_TENANT_ID를 파드에 주입합니다. 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 발급 토큰입니다. 레이블이 지정된 파드 내부에서 토큰 획득 및 사용하기의 cURL 샘플 1단계를 실행하고 결과를 디코딩하세요. 관리 ID 경로와 동일한 클레임 형태를 가집니다:
{
"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의 객체 ID이고, aud는 대상 앱 등록의 클라이언트 ID이며, azp는 관리 ID의 클라이언트 ID(AZURE_CLIENT_ID의 값)입니다. 수명은 관리 ID 경로와 다릅니다. client_credentials 토큰은 기본적으로 iat와 exp 사이가 24시간이 아닌 무작위 60~90분 범위입니다.
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
}Connect workload 마법사의 Microsoft Entra 타일은 max_jwt_lifetime_seconds를 7500(2시간 조금 넘음)으로 설정하여 발급자를 생성하며, 이는 client_credentials 토큰의 기본 60~90분 수명을 커버합니다. 테넌트 토큰 수명 정책이나 Continuous Access Evaluation(CAE)은 해당 수명을 연장할 수 있습니다. 디코딩된 토큰의 exp에서 iat를 뺀 값이 7500초를 초과하면 Settings → Workload identity → Issuers에서 발급자를 편집하고 max_jwt_lifetime_seconds를 그에 맞게 올리세요. 그렇지 않으면 교환이 invalid_grant로 실패합니다. 테넌트에서 관리 ID 사용하기의 관리 ID 워크로드도 실행하는 경우, 두 경로를 모두 커버하는 해당 섹션의 86400 값을 사용하세요.
허용되는 수명이 길수록 유출된 Entra 토큰이 더 오래 교환 가능한 상태로 유지됩니다. 토큰이 유출되면 페더레이션 규칙을 비활성화하는 것이 대응 수단이며, 규칙 범위 지정하기에 설명된 대로 엄격한 oid 매칭은 애초에 토큰을 교환할 수 있는 ID를 제한합니다.
페더레이션 규칙: 관리 ID의 객체 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가 이를 자동으로 갱신합니다.
런타임에 파드는 2단계 교환을 수행합니다. Kubernetes가 프로젝션한 토큰(AZURE_FEDERATED_TOKEN_FILE의 파일)을 페더레이션된 client_credentials 어설션으로 Entra의 토큰 엔드포인트에 보낸 다음, 결과로 받은 Entra 액세스 토큰을 POST /v1/oauth/token에서 교환합니다. 다음 예제에서 볼 수 있듯이 Entra 가져오기를 토큰 제공자 콜러블로 제공하면 각 Anthropic SDK가 두 번째 교환과 갱신 루프를 처리합니다. cURL 탭은 원시 흐름을 보여줍니다.
샘플에는 서로 다른 두 개의 클라이언트 ID가 나타납니다. <APP_ID>는 토큰 대상 등록하기의 대상 앱 등록 클라이언트 ID이며, api://<APP_ID>/.default 범위는 Entra에 해당 대상으로 지정된 토큰을 요청합니다. $AZURE_CLIENT_ID는 웹훅이 주입한 관리 ID의 클라이언트 ID이며 호출자를 식별합니다. 둘을 서로 바꿔 사용하지 마세요.
워크로드가 이미 Azure Identity 클라이언트 라이브러리를 사용하는 경우, 2단계 교환을 직접 수행하는 대신 해당 라이브러리의 토큰 획득(api://<APP_ID>/.default 범위를 사용하는 DefaultAzureCredential)을 ID 토큰 제공자로 전달하세요. 라이브러리는 동일한 AZURE_FEDERATED_TOKEN_FILE, AZURE_CLIENT_ID, AZURE_TENANT_ID 환경 변수를 읽고 Entra 교환을 처리합니다.
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"))레이블이 지정된 파드 내부에서 토큰 획득 및 사용하기에 표시된 cURL 교환을 실행하고 POST /v1/oauth/token이 sk-ant-oat01-로 시작하는 access_token과 초 단위의 expires_in 값을 포함한 200을 반환하는지 확인합니다. 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입니다.azp가 아닌 appid에 담습니다. 토큰이 v1.0인 경우를 참조하세요.이 가이드는 대상 앱 등록을 api.requestedAccessTokenVersion: 2로 구성하므로 표시되는 모든 토큰은 v2.0입니다. requestedAccessTokenVersion을 설정하지 않은 기존 등록을 재사용하면 Entra는 대신 v1.0 토큰을 발급합니다. 샘플 토큰을 디코딩하고 ver 클레임을 확인하세요. 1.0이면 네 가지가 달라집니다:
iss 클레임은 https://login.microsoftonline.com/<TENANT_ID>/v2.0이 아닌 https://sts.windows.net/<TENANT_ID>/입니다. 토큰의 iss 클레임에 있는 그대로 발급자 URL을 등록하세요. 두 URL은 동일한 JWKS를 공유하므로 검색 모드는 둘 다에서 작동합니다.aud 클레임은 등록의 클라이언트 ID가 아니라 resource로 전달한 식별자 URI(예: api://<APP_ID>)입니다. 페더레이션 규칙의 audience를 디코딩된 토큰의 정확한 aud 값으로 설정하세요.azp가 아닌 appid에 나타납니다. 두 클레임은 동일한 토큰에 함께 나타나지 않으므로 azp를 매칭하는 규칙은 v1.0 토큰에 대해 절대 통과하지 않습니다.oid, sub, tid 클레임은 두 버전에서 동일한 값을 가지므로 이 가이드의 나머지 부분은 변경 없이 적용됩니다.
페더레이션 규칙은 claims 맵에 더해(또는 대신) subject_prefix로 토큰의 주체를 매칭할 수 있습니다. 필드가 결합되는 방식은 규칙 매칭 의미론을 참조하세요. 이러한 ID에 대한 Entra sub 값은 고정 길이의 정규 GUID이므로, 전체 36자 객체 ID를 포함하는 subject_prefix는 해당 주체만 매칭합니다. 이는 Entra의 주체 형식의 속성이며 subject_prefix 일반의 속성이 아닙니다.
테넌트의 모든 ID가 등록된 대상에 대한 토큰을 요청할 수 있으므로,
audience와 tid만으로는 특정 워크로드를 식별할 수 없습니다. oid(또는
azp/appid) 매칭을 생략하거나 와일드카드 또는 부분 GUID
subject_prefix를 사용하는 규칙은 테넌트의 모든 관리 ID와 서비스
주체를 승인합니다.
규칙의 match 블록을 사용 사례에 맞는 가장 좁은 범위로 제한하세요:
oid를 정확한 값으로 매칭: claims.oid를 관리 ID의 전체 객체 ID로 설정합니다. 해당 전체 객체 ID로 설정된 subject_prefix는 동등합니다(Console 마법사는 둘 다 설정합니다). 의도한 것보다 더 많은 ID를 매칭하는 와일드카드나 부분 GUID subject_prefix는 절대 사용하지 마세요.tid 고정: 발급자 URL이 이미 테넌트를 고정하지만, claims.tid를 추가하면 발급자 레코드가 나중에 편집될 경우의 구성 드리프트를 방지합니다.audience를 디코딩된 토큰의 정확한 aud 값으로 설정하여 다른 애플리케이션용으로 발급된 토큰이 거부되도록 합니다.Was this page helpful?