Okta 可以充当工作负载身份提供方,通过 OAuth 2.0 的 client_credentials 授权方式向服务应用程序颁发 OIDC 访问令牌。您的工作负载向 Okta 进行身份验证(通常使用 private_key_jwt,因此无需存储共享密钥),接收一个已签名的 "JSON Web Token"(JSON Web 令牌),即 JWT,然后将该 JWT 与 Anthropic 交换以获取短期有效的访问令牌。
Okta 授权服务器的颁发者 URL 格式为 https://<your-domain>.okta.com/oauth2/<auth-server-id>。如果您使用内置的默认服务器,则路径为 /oauth2/default。
您必须使用 Okta 自定义授权服务器(包括 default 服务器)。由 Okta 组织授权服务器直接颁发的令牌(即路径中不含授权服务器 ID 的 /oauth2/v1/token 端点)无法被外部方验证,因为 Okta 不会为其发布签名密钥。
配置 Okta 和向 Okta 进行身份验证的方式有很多种,这些内容超出了本文档的范围。请确保您的配置和身份验证机制遵循贵公司的指导方针和安全实践。
/v1/token 端点请求令牌并访问 api.anthropic.com 的工作负载。总体而言,您需要:
具体的导航路径取决于您的 Okta 组织配置和管理控制台版本。以下编号步骤介绍了一种常见的操作路径:
private_key_jwt)并注册您工作负载的公共 JWK。或者,如果您的环境能够安全地存储客户端密钥,也可以使用客户端密钥。对于以下示例,您可能需要在应用程序上禁用 DPoP 要求;请确保您的生产环境设置符合贵组织的安全要求。https://api.anthropic.com,以便颁发的访问令牌携带该 aud 声明。Anthropic 会根据此固定值验证 aud。anthropic.access)。Okta 会拒绝不包含已授予作用域的 client_credentials 请求。对于使用 client_credentials 的服务应用,Okta 会将所颁发访问令牌的 sub 声明设置为该应用程序的 Client ID,并将 iss 设置为授权服务器的颁发者 URL。
按照设置演练在 Claude Console 中注册联合颁发者、创建 Anthropic 服务账号并创建联合规则。请使用以下 Okta 特定的值。
联合颁发者: 使用您的 Okta 自定义授权服务器 URL 和发现模式。Anthropic 会读取 Okta 的 .well-known/openid-configuration 发现文档,并从其公布的 jwks_uri 获取 JWKS。
{
"name": "okta-prod",
"issuer_url": "https://acme.okta.com/oauth2/aus1a2b3c4d5e6f7g8h9",
"jwks_source": "discovery"
}联合规则: 基于 Okta 的 sub 声明进行匹配,该声明即为服务应用的 Client ID。如果您在 Okta 中定义了自定义声明,则可以改为使用 claims 映射或 CEL condition 对这些声明进行匹配。
{
"name": "okta-pipeline",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "0oa1b2c3d4e5f6g7h8i9",
"audience": "https://api.anthropic.com"
},
"target": { "type": "service_account", "service_account_id": "svac_..." },
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}与平台原生提供方(AWS、Google Cloud、Kubernetes)不同——它们会在工作负载的运行时内部提供令牌(通过投射文件或本地元数据端点)——Okta 不会这样做。您的工作负载必须调用 Okta 的令牌端点以获取 JWT,然后将该 JWT 作为身份令牌传递给 Anthropic SDK。
import os
import httpx
import anthropic
from anthropic import WorkloadIdentityCredentials
def fetch_okta_token() -> str:
response = httpx.post(
f"{os.environ['OKTA_ISSUER']}/v1/token",
data={
"grant_type": "client_credentials",
"scope": "anthropic.access",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
# 构建 RFC 7523 client_assertion JWT,使用您的 Okta 应用私钥进行签名
"client_assertion": build_signed_client_assertion(),
},
)
response.raise_for_status()
return response.json()["access_token"]
client = anthropic.Anthropic(
credentials=WorkloadIdentityCredentials(
identity_token_provider=fetch_okta_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, Claude"}],
)
print(message.content[0].text)每个 SDK 选项卡都展示了可调用模式:每当 Anthropic 访问令牌接近过期时,Anthropic SDK 会再次调用您的身份令牌提供程序,因此您的 Okta 令牌获取器应在每次调用时返回一个新令牌,而不是无限期地缓存同一个令牌。ant CLI 会在每次交换时重新读取 ANTHROPIC_IDENTITY_TOKEN_FILE,因此对于长时间运行的 shell,请通过定时器刷新该文件。
成功的交换会返回一个以 sk-ant-oat01- 开头的 access_token 以及一个以秒为单位的 expires_in 值。如果遇到 400 invalid_grant,请参阅排查交换失败问题;Okta 端最常见的原因是 issuer_url 不匹配(它必须包含 /oauth2/<auth-server-id> 路径;Okta 组织授权服务器不可用于此目的)。
同一 Okta 授权服务器下的多个服务应用共享同一个颁发者。省略 subject_prefix 的规则会匹配该服务器上的每一个服务应用,因此任何能够注册服务应用的团队都可能获取联合的 Anthropic 令牌。
将规则的 match 块锁定到适合您用例的最小范围:
subject_prefix 设置为服务应用的完整 Client ID,且不带尾随的 *。audience 值,以便拒绝为其他受众签发的令牌。claims 映射或 CEL condition 对其进行匹配。Was this page helpful?