WIF 参考
Workload Identity Federation 的环境变量、验证规则、配置文件配置和错误参考。
本页汇总了 Workload Identity Federation 的配置项、验证约束和错误映射。有关设置演练,请参阅提供商指南。
令牌交换请求
POST /v1/oauth/token 接受使用 RFC 7523 jwt-bearer 授权的 JSON 请求体。SDK 会根据环境变量为您构建此请求;每个提供商指南中的 cURL 示例展示了原始请求体。
| 字段 | 必需 | 描述 |
|---|---|---|
grant_type | 是 | 始终为 urn:ietf:params:oauth:grant-type:jwt-bearer。 |
assertion | 是 | 由您的身份提供商签发的 OIDC JWT。 |
federation_rule_id | 是 | 要评估的联合规则的带标签 ID(fdrl_...)。 |
organization_id | 是 | 您的 Anthropic 组织的 UUID。 |
service_account_id | 是 | 目标服务账户的带标签 ID(svac_...)。 |
workspace_id | 视情况而定 | 签发的令牌所限定的工作区的带标签 ID(wrkspc_...)。当规则在多个工作区中启用时为必需。省略时,服务器会选择该规则唯一启用的工作区。字面值 default 也可用于组织的默认工作区,但已弃用;请使用该工作区的 wrkspc_... ID。 |
令牌交换响应
POST /v1/oauth/token 返回标准的 OAuth 2.0 令牌响应(RFC 6749 §5.1):
| 字段 | 类型 | 描述 |
|---|---|---|
access_token | string | 短期有效的 Anthropic 令牌,前缀为 sk-ant-oat01-...。以 Authorization: Bearer <token> 形式传递。 |
token_type | string | 始终为 Bearer。 |
expires_in | integer | 令牌过期前的秒数。 |
scope | string | 匹配规则授予的 OAuth 范围。 |
环境变量
SDK 读取这些变量,以便在不传入任何构造函数参数的情况下执行联合令牌交换。
| 变量 | 必需 | 描述 | 示例 |
|---|---|---|---|
ANTHROPIC_FEDERATION_RULE_ID | 是 | 要评估的联合规则的带标签 ID。 | fdrl_... |
ANTHROPIC_ORGANIZATION_ID | 是 | 您的 Anthropic 组织的 UUID。可在 Claude Console 的组织页面(platform.claude.com/settings/organization)上找到。 | 00000000-0000-0000-0000-000000000000 |
ANTHROPIC_IDENTITY_TOKEN_FILE | _TOKEN_FILE 或 _TOKEN 二选一 | 由您的身份提供商(IdP)签发的 JWT 的文件系统路径。SDK 在每次交换时都会重新读取此文件,以确保在磁盘上轮换的投射令牌始终是最新的。 | /var/run/secrets/anthropic.com/token |
ANTHROPIC_IDENTITY_TOKEN | _TOKEN_FILE 或 _TOKEN 二选一 | 字符串形式的 JWT 字面值。当您的平台以环境变量而非文件的形式注入令牌时使用。 | eyJhbGciOiJSUzI1NiIs... |
ANTHROPIC_SERVICE_ACCOUNT_ID | 是 | 签发的访问令牌所代表的目标 Anthropic 服务账户的带标签 ID。 | svac_... |
ANTHROPIC_WORKSPACE_ID | 视情况而定 | 签发的令牌所限定的工作区的带标签 ID。当联合规则在多个工作区中启用时为必需;当规则绑定到单个工作区时为可选。签发的令牌在交换时即被限定到此工作区,因此切换工作区需要重新交换。字面值 default 也可用于默认工作区,但已弃用;请使用其 wrkspc_... ID。 | wrkspc_... |
ANTHROPIC_PROFILE | 否 | 要加载的配置文件名称。优先于此表中的联合环境变量。 | staging-profile |
仅当 ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 以及 ANTHROPIC_IDENTITY_TOKEN_FILE 或 ANTHROPIC_IDENTITY_TOKEN 之一全部设置时,直接环境变量联合路径才会激活。ANTHROPIC_WORKSPACE_ID 会一并读取,但不影响激活。
凭据优先级
SDK 按以下顺序解析凭据。第一个产生凭据的来源胜出。
| 顺序 | 来源 | 说明 |
|---|---|---|
| 1 | 构造函数参数(api_key=、auth_token=、credentials=) | 始终覆盖其他所有来源。 |
| 2 | ANTHROPIC_API_KEY 或 ANTHROPIC_AUTH_TOKEN | 完全遮蔽联合。从 API 密钥迁移时请取消设置这些变量。 |
| 3 | ANTHROPIC_PROFILE | 加载 <config_dir>/configs/<name>.json。缺少指定名称的配置文件会报错,而不会回退。 |
| 4 | 联合环境变量 | ANTHROPIC_FEDERATION_RULE_ID + ANTHROPIC_ORGANIZATION_ID + ANTHROPIC_SERVICE_ACCOUNT_ID + ANTHROPIC_IDENTITY_TOKEN[_FILE]。 |
| 5 | 活动配置文件 | 从 <config_dir>/active_config 解析,回退到名为 default 的配置文件。 |
在 ant CLI 中,Claude Models on Google Cloud (Anthropic managed) 的设置优先级低于联合身份(federation)环境变量,高于活动配置文件(profile)。这些设置包括项目、工作区 ID 和位置。您可以通过 --google-cloud-* 标志或 ANTHROPIC_GOOGLE_CLOUD_* 变量来设置它们。只要设置了其中任意一项,CLI 就会使用这些设置。使用这些设置时,CLI 会从 Google Application Default Credentials(应用默认凭据)获取凭据。
加载配置文件时,环境变量会填充配置文件省略的字段,但绝不会覆盖配置文件显式设置的字段。例如,仅当活动配置文件未设置 workspace_id 时,ANTHROPIC_WORKSPACE_ID 才会填充该字段。
配置文件
"Profile"(配置文件)是 SDK 和 ant CLI 都会读取的命名配置文件。借助配置文件,您可以将联合参数随容器镜像一起发布,或在不更改代码的情况下切换环境。
配置目录
SDK 按以下顺序定位配置目录:
$ANTHROPIC_CONFIG_DIR- Linux 和 macOS 上为
~/.config/anthropic - Windows 上为
%APPDATA%\Anthropic
活动配置文件
活动配置文件名称按以下顺序解析:
$ANTHROPIC_PROFILE<config_dir>/active_config的内容(由ant profile activate <name>写入的单行文件)- 字面名称
default
Claude Code 和 Claude Agent SDK 遵循相同的解析顺序,因此在此处配置的联合配置文件无需额外设置即可为这些工具进行身份验证。
文件布局
| 路径 | 内容 | 敏感性 |
|---|---|---|
<config_dir>/configs/<profile>.json | version、authentication 块、organization_id、workspace_id 和 base_url。 | 非机密。可以安全地提交或打包进镜像。 |
<config_dir>/credentials/<profile>.json | version、缓存的 access_token、expires_at,以及(用于交互式登录的)refresh_token。 | 机密。由 SDK 以 0600 模式写入。 |
配置文件和凭据文件都带有一个 major.minor 格式的顶层字符串 version 字段(当前为 "1.0")。SDK 会自动写入此字段,以便未来版本能够检测并迁移旧格式;手动编写配置时可以省略该字段,SDK 会将该文件视为当前版本。
联合配置文件示例
{
"version": "1.0",
"authentication": {
"type": "oidc_federation",
"federation_rule_id": "fdrl_...",
"service_account_id": "svac_...",
"identity_token": {
"source": "file",
"path": "/var/run/secrets/anthropic.com/token"
}
},
"organization_id": "00000000-0000-0000-0000-000000000000",
"workspace_id": "wrkspc_...",
"base_url": "https://api.anthropic.com"
}如果省略 authentication.identity_token,SDK 会回退到环境中的 ANTHROPIC_IDENTITY_TOKEN_FILE 或 ANTHROPIC_IDENTITY_TOKEN。
OAuth 范围
您在联合规则上设置的 oauth_scope 决定了签发的访问令牌可以调用哪些 Claude API 端点。
| 范围 | 授予访问权限 |
|---|---|
workspace:developer | 规则所在工作区中所有非管理类 Claude API 端点:Messages(包括流式传输和令牌计数)、Models、Managed Agents 及其会话、Files 和 Skills。这与同一工作区中工作区 API 密钥所拥有的访问权限一致。 |
workspace:inference | 规则所在工作区中的推理端点:Messages(包括流式传输和令牌计数)、Models 以及 OpenAI 兼容的聊天端点。适用于只需调用 Claude、从不需要管理 Files、Skills 或其他资源的工作负载。 |
workspace:manage_tunnels | MCP 隧道 API:创建、列出和获取隧道,注册和归档 CA 证书,显示和轮换隧道令牌,以及归档隧道。当您从 Console 的创建隧道模态窗口创建规则时,该窗口会锁定此范围。 |
org:admin | 对 Admin API 的完全访问权限(组织成员、邀请、工作区、API 密钥等)。OAuth org:admin 令牌只能创建或修改范围为 workspace:developer 或 workspace:inference 的规则,并且无法更新支撑任何其他范围规则的颁发者;请参阅约束。 |
对令牌范围之外的端点发出的请求会返回 HTTP 403。目前不提供更细粒度的范围(按资源,或读与写)。
权限边界
联合规则的 oauth_scope 是一个上限:签发的令牌永远不能超出它。目标服务账户的 organization_role(developer 或 admin)决定了哪些范围可以授予,因此授予 org:admin 的规则必须以 organization_role=admin 的服务账户为目标。有效权限是规则范围与服务账户角色的交集。
规则 oauth_scope | 服务账户 organization_role | 有效权限 |
|---|---|---|
workspace:developer | admin | 仅限规则所在工作区中的 Claude API 访问。范围将令牌限制在角色之下。 |
org:admin | admin | 完全的 Admin API 访问权限(组织成员、邀请、工作区、API 密钥等),但不包括针对 OAuth 调用方的例外限制;请参阅约束。 |
验证规则
Anthropic 在您创建或更新颁发者和规则时,以及在交换时验证传入的 JWT 时,会强制执行这些约束。
有关完整的参数详情和响应架构,请参阅服务账户 API 参考、联合颁发者 API 参考和联合规则 API 参考。
资源字段
| 字段 | 约束 |
|---|---|
颁发者、规则和服务账户的 name | 必须匹配 ^[a-z0-9-]+$,长度为 1 到 255 个字符。 |
workspace_id | 创建时必需,除非 applies_to_all_workspaces 为 true。在此规则下签发的令牌所适用的配额、计费和速率限制所属的工作区(wrkspc_...)。必须是同一组织中的工作区,且目标服务账户必须是该工作区的成员。 |
applies_to_all_workspaces | 布尔值。设置为 true 可在组织的每个工作区中启用该规则,而不是指定某一个工作区;创建时必须提供此字段或 workspace_id 之一。 |
token_lifetime_seconds | 介于 60 和 86400 之间的整数(1 分钟到 24 小时)。默认值为 3600。超出此范围的值会在请求时被拒绝。请参阅令牌有效期和刷新。 |
URL 字段
issuer_url、jwks.discovery_base 和 jwks.url 字段会经过验证:
| 约束 | 详情 |
|---|---|
| 协议 | 必须为 https。 |
| 端口 | 必须为 443(显式或默认)。 |
| 主机 | 必须是您的 OIDC 提供商的公共 DNS 主机名。必须解析为公共 IP 地址;不接受 IP 字面量。 |
URL 验证失败会返回 400 invalid_request_error,错误消息以字段名作为前缀(例如 issuer_url: url must use https scheme)。
JWT 验证
| 约束 | 详情 |
|---|---|
| 最大大小 | assertion JWT 最多为 16 KiB。 |
| 签名算法 | 仅接受非对称算法(RSA 和 ECDSA 系列:ES256、ES384、ES512、RS256、RS384、RS512、PS256、PS384、PS512)。HMAC(HS256、HS384、HS512)和 none 会被拒绝。 |
| 密钥 ID | JWT 头部必须携带与颁发者 JWKS 中某个密钥匹配的 kid。没有 kid 的令牌会被拒绝。 |
| 必需声明 | 必须存在 sub。必须存在 iat 且不能是未来时间。必须存在 exp 且必须是未来时间。 |
| 一次性使用 | 携带 jti 声明的断言在每个颁发者下只能交换一次:使用相同 jti 重复交换会被视为重放而拒绝。颁发者的 check_jti 字段(默认启用)控制此检查;没有 jti 声明的断言不受此检查约束。请参阅联合颁发者 API 参考。 |
| 最长有效期 | 令牌的有效期(exp 减去 iat)不得超过颁发者配置的最大值(默认为 1 小时,可在 Claude Console 中为每个颁发者配置)。 |
| 时钟偏差 | 对 exp、nbf 和 iat 应用 30 秒的容差。 |
规则匹配语义
联合规则的 match 块决定是否接受传入的 JWT。所有已填写的字段均以 AND 语义进行评估:JWT 必须满足每个已填写的匹配器。必须至少设置 subject_prefix、claims 或 condition 之一;仅包含 audience(或完全没有匹配器)的 match 块会被拒绝。这可以防止出现接受某个颁发者所有令牌的规则。
| 匹配器 | 类型 | 语义 |
|---|---|---|
subject_prefix | string | 与 JWT sub 声明精确匹配。末尾的 * 使其成为前缀匹配(sub 值必须以 * 之前的字符开头)。区分大小写。 |
audience | string | JWT aud 声明必须包含此精确字符串。当 aud 为数组时,任一元素精确匹配即满足检查。 |
claims | map<string, string> | 每个键是一个顶层声明名称,每个值是所需的精确字符串值。对于嵌套、数值、布尔或列表和映射等复杂声明,请改用带 CEL 表达式的 condition。 |
condition | string (CEL) | 必须求值为 true 的 CEL 表达式。 |
CEL 求值环境
condition 表达式可以访问一个变量:
| 变量 | 类型 | 内容 |
|---|---|---|
claims | map | 完整解码的 JWT 声明集。嵌套对象可作为嵌套映射访问。 |
示例:
claims.sub.startsWith("repo:acme-corp/") && claims.ref in ["refs/heads/main", "refs/heads/release"]错误
令牌交换错误
POST /v1/oauth/token 以标准的 API 错误格式返回错误。SDK 将交换失败报告为 WorkloadIdentityError,其中包含 HTTP 状态以及响应体中的错误详情。在 Python、TypeScript 和 Ruby 中,请求 ID 位于错误对象上;在 Java 中,位于异常的响应头中。在 Go 中,它仅出现在错误消息中,因为错误类型位于内部包中;C# 和 PHP 的错误不携带请求 ID。
| 状态 | 错误 | 原因 | 解决方法 |
|---|---|---|---|
| 400 | invalid_request_error | federation_rule_id 格式错误,或缺少必需的请求字段。 | 验证 fdrl_ ID,并确认请求体包含所有必需字段。 |
| 400 | invalid_request_error | 存在 workspace_id,但它既不是格式正确的 wrkspc_... ID,也不是字面值 default。 | 修正 workspace_id 值;响应消息会指明预期格式。 |
| 401 | authentication_error | JWT iss 声明与注册的 issuer_url 不完全相等。 | 逐字节比较,包括末尾斜杠和协议:jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson | .iss' <<< "$JWT"。 |
| 401 | authentication_error | JWKS 获取失败、JWKS 已过时,或 JWT 使用了不在 JWKS 中的密钥签名。 | 对于 inline 模式,使用轮换后的密钥更新颁发者。对于 discovery 和 explicit_url,确认 JWKS 端点可通过 443 端口访问;如果颁发者最近轮换了签名密钥,请参阅密钥轮换和缓存。 |
| 401 | authentication_error | JWT exp 声明已过期(超出 30 秒偏差窗口)。 | 确认您的身份提供商正在投射新的令牌,并且 SDK 正在重新读取令牌文件。 |
| 401 | authentication_error | JWT 已通过验证,但其声明不满足规则的 match 块。 | 解码 JWT 并将每个声明与规则进行比较。subject_prefix 区分大小写。audience 要求元素精确匹配。 |
| 401 | authentication_error | federation_rule_id 不存在、已归档,或 JWT 未获得该规则的授权(合并为同一错误以防止枚举)。 | 在 Claude Console 中确认规则 ID,并确认该规则未被归档。 |
| 401 | authentication_error | 联合规则在多个工作区中启用,而请求省略了 workspace_id。身份验证历史记录条目显示原因为 workspace_id_required。 | 将 ANTHROPIC_WORKSPACE_ID(或原始请求中的 workspace_id 请求体字段)设置为您希望令牌限定到的 wrkspc_... ID。请参阅令牌交换请求。 |
无论哪项检查失败,每次断言拒绝都会返回相同的不透明 401 authentication_error,消息固定为 Authentication failed;可区分的错误会让调用方能够探测规则配置。拒绝原因记录在 Claude Console 中身份验证历史记录的该次尝试条目上,例如当 sub 声明不满足规则的 subject_prefix 时为 match_subject_prefix,或当规则跨多个工作区而请求未指定任何工作区时为 workspace_id_required。在确认规则所属组织之前就被拒绝的请求(上述 400 invalid_request_error 类错误)不会留下历史记录条目;其响应消息会直接指明问题。没有匹配历史记录条目的 401 通常意味着 federation_rule_id 本身未被识别。
常见的 SDK 端故障
| 症状 | 原因 | 解决方法 |
|---|---|---|
| SDK 报告"no credentials"而不是执行交换 | ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID 或 ANTHROPIC_IDENTITY_TOKEN[_FILE] 之一未设置,且没有活动配置文件。 | 设置全部四个变量,或配置一个配置文件。 |
| SDK 使用 API 密钥进行身份验证而不是联合 | 设置了 ANTHROPIC_API_KEY 或 ANTHROPIC_AUTH_TOKEN,并在优先级中胜出。 | 取消设置密钥或令牌变量。 |
首次请求时出现 FileNotFoundError | ANTHROPIC_IDENTITY_TOKEN_FILE 中的路径不存在。SDK 在交换时才延迟打开该文件。 | 确认投射令牌卷已挂载且路径匹配。 |
| 令牌交换成功,但 Claude API 请求返回 403 | 签发令牌的范围未授予对该端点的访问权限。 | 对照 OAuth 范围检查规则的 oauth_scope。 |
| 因凭据为空而身份验证失败 | 某个凭据环境变量已导出但设置为空字符串。空值可能仍会占据其优先级位置。 | 使用 unset VAR 而不是 VAR="" 取消设置该变量。 |
排查交换失败
401 authentication_error 响应是有意设计为不透明的,其消息始终为 Authentication failed;拒绝原因记录在身份验证历史记录中,而不在响应中。
一种常见的不透明故障是断言重放:携带 jti 声明的断言只能交换一次,因此重新发送同一 JWT 的工作负载(重试循环,或重新读取未轮换令牌的刷新操作)会在第二次交换时被拒绝。身份验证历史记录页面会以原因 jti_reused 显示这些尝试;解决方法是为每次交换签发新的断言。
如果您仍需要从 JWT 本身进行调试,请按顺序完成以下检查:
解码 JWT
解码您发送的断言,以便将每个声明与您的颁发者和规则配置进行比较:
cURLjq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson' <<< "$JWT"检查 iss 是否与颁发者匹配
解码后的
iss声明必须与注册的issuer_url逐字节相等,包括协议、端口和任何末尾斜杠。哪怕只有一个字符不匹配,验证也会失败。检查 aud 是否与规则匹配
解码后的
aud声明必须包含与规则的audience值精确匹配的内容。当aud为数组时,必须有一个元素精确匹配。检查 sub 和每个 claims 条目
将
sub与规则的subject_prefix进行比较(区分大小写;末尾的*表示前缀匹配,其他情况为精确匹配)。将规则claims映射中的每个键与同名的顶层声明进行比较。检查 exp、nbf 和 iat
exp必须是未来时间,nbf/iat必须是过去时间,均在 30 秒偏差窗口内。如果工作负载主机的时钟发生漂移,原本有效的令牌也会被拒绝。检查 JWKS 可达性
对于
discovery模式,通过 443 端口上的公共 HTTPS 获取<jwks.discovery_base or issuer_url>/.well-known/openid-configuration,并确认jwks_uri可以解析。对于explicit_url,直接获取 JWKS URL。对于inline,确认自您注册密钥以来颁发者的签名密钥未发生轮换。如果颁发者轮换了签名密钥并立即开始使用它签名,在 Anthropic 的 JWKS 缓存刷新期间,交换可能会失败长达一分钟。请参阅密钥轮换和缓存。
JWKS 来源模式
注册联合颁发者时,jwks 字段控制 Anthropic 如何获取用于验证该颁发者 JWT 签名的公钥。它是一个以 type 为键的可辨识联合:
jwks.type | jwks 结构 | 行为 | 适用场景 |
|---|---|---|---|
discovery(默认) | { "type": "discovery", "discovery_base": "https://..." }(discovery_base 为可选;当发现 URL 与 issuer_url 不同时设置) | Anthropic 获取 <discovery_base or issuer_url>/.well-known/openid-configuration,从发现文档中读取 jwks_uri,然后从该处获取 JWKS。 | 您的 IdP 在公共互联网上提供标准的 OIDC 发现文档。大多数托管提供商(EKS、GKE、Cloud Run、GitHub Actions、Entra ID)都支持此方式。 |
explicit_url | { "type": "explicit_url", "url": "https://..." } | Anthropic 直接从 url 获取 JWKS。issuer_url 仅用于与 JWT iss 声明进行字符串比较,从不会被连接。 | 您的 IdP 不提供发现文档,或发现文档仅限内部访问但 JWKS 可公开访问。 |
inline | { "type": "inline", "keys": [...] } | 您以内联方式提供 JWK 对象数组(JWKS 文档中的 keys 数组,而不是外层包装对象)。Anthropic 不发出任何出站请求。issuer_url 仅用于 iss 比较。 | 隔离网络环境、使用集群内部颁发者 URL 的自管理 Kubernetes 集群,或者您希望显式控制密钥轮换时。 |
可辨识联合在结构上使配套字段互斥。discovery 和 explicit_url 还都接受一个可选的 ca_cert_pem 字符串,用于通过私有 CA 提供 TLS 的颁发者。
密钥轮换和缓存
在 discovery 和 explicit_url 模式下,Anthropic 会缓存获取到的 JWKS。如果您的身份提供商发布了新的签名密钥并立即开始使用它签名令牌,那么在缓存刷新期间,提交这些令牌的交换可能会因签名错误而失败,最长持续 1 分钟。
为避免出现此窗口期,请在您的身份提供商开始使用新签名密钥签名令牌之前至少 15 分钟将其发布到 JWKS 中,并将被替换的密钥保留在 JWKS 中,直到由其签名的令牌过期。托管身份提供商通常会自行遵循这一规范。如果您运营自己的颁发者(自管理 Kubernetes 集群、SPIRE OIDC 发现提供商,或配置了轮换周期的 Okta 自定义授权服务器),请确认您的轮换策略会在首次使用之前发布新密钥。
Was this page helpful?