SpyBara
Go Premium

self-hosted-environments-identity.md 2026-09-27 23:59 UTC to 2026-09-28 22:01 UTC

This page contains 2 additions and 2 deletions.

2026
Sat 12 03:02 Fri 18 23:58 Mon 28 22:59

在自託管環境中驗證工作階段身分

驗證 CLAUDE_CODE_SESSION_ACCESS_TOKEN JWT,以便您網路上的服務可以信任來自自託管環境中工作階段的請求。

自託管環境讓 Claude Code 雲端工作階段在您操作的基礎設施上執行,而不是在 Anthropic 的基礎設施上執行。由於工作階段在您的網路內執行,Claude 可以直接呼叫您的內部服務。這些服務需要一種方式來確認請求來自您環境中的 Claude Code 工作階段,並識別建立該工作階段的使用者或服務身分。

自託管環境中的每個工作階段都會在 CLAUDE_CODE_SESSION_ACCESS_TOKEN 環境變數中收到一個簽署的 JSON Web Token (JWT)。工作階段會像任何持有人認證一樣呈現令牌;例如,Claude 執行的指令碼可以使用 curl -H "Authorization: Bearer $CLAUDE_CODE_SESSION_ACCESS_TOKEN" 呼叫您的服務。Anthropic 簽署令牌並在公開 JWKS 端點發佈驗證金鑰。您的服務會擷取這些金鑰、驗證簽章,並讀取宣告以決定要授予什麼存取權限。

工作階段令牌

在您編寫驗證程式碼之前,請了解令牌建立的內容以及您的 JWT 程式庫將看到的形狀。

令牌證明的內容

有效的令牌建立了一些事實,並刻意不建立其他事實:

  • 證明:Anthropic 為特定環境中的特定工作階段簽發了令牌,以及工作階段的建立方式:由您組織中的使用者建立,或由您組織的服務身份建立,這是 Claude Tag 頻道工作階段的啟動方式
  • 不證明:執行者主機上的哪個程序呈現它。令牌位於工作階段內的環境變數中,因此 Claude 執行的任何程式碼以及工作階段啟動的任何工具或 MCP 伺服器都可以讀取並呈現它。

對您的服務有兩個後果:

  • 根據您的環境 ID(在雲端環境管理頁面上與您的環境一起顯示的 ccpool_... 值)驗證 aud 聲明,以拒絕簽發給任何其他組織環境的令牌。
  • 將您從令牌衍生的認證範圍限制在單個編碼工作階段應該能夠執行的操作,而不是工作階段建立者可以執行的所有操作。請參閱範圍衍生認證。

令牌格式

CLAUDE_CODE_SESSION_ACCESS_TOKEN 的值具有 sk-ant-cc- 前綴,後面跟著標準的三部分 JWT:

sk-ant-cc-<base64url header>.<base64url payload>.<base64url signature>

在將值傳遞給 JWT 程式庫之前,請移除前綴。簽發給 Anthropic 託管雲端工作階段的令牌改為帶有 sk-ant-si- 前綴,並由不同的金鑰集簽署,因此拒絕任何不以 sk-ant-cc- 開頭的值。

簽名演算法是 ES256,這是 P-256 曲線上的 ECDSA,使用 SHA-256。令牌標頭帶有一個 kid,用於識別 JWKS 中的哪個金鑰簽署了它。

驗證令牌

驗證在兩個地方之一執行。您網路上的服務根據 Anthropic 發佈的金鑰對令牌進行密碼學驗證,工作階段內的包裝指令碼可以改為使用執行者二進位檔案的內建解碼器。

從您的服務驗證令牌

Anthropic 在公開、未經驗證的端點發佈驗證金鑰:

https://api.anthropic.com/v1/code/.well-known/jwks.json

回應是標準的 JSON Web Key Set。Anthropic 定期輪換簽署金鑰,輪換前的金鑰會在集合中保留足夠長的時間,以便它們簽署的令牌繼續驗證,因此不要固定單個金鑰。端點設定 Cache-Control: public, max-age=300,因此快取金鑰集並每五分鐘重新取得一次是安全的。

根據這些檢查驗證每個傳入令牌:

1

檢查前綴

如果值不以 sk-ant-cc- 開頭,則拒絕該值,然後移除該前綴。其餘部分是標準的緊湊 JWT。

2

驗證簽名

取得 JWKS,選擇其 kid 與令牌標頭相符的金鑰,並驗證 ES256 簽名。拒絕其 alg 標頭不是 ES256 的令牌。如果令牌到達時帶有您快取的金鑰集中沒有的 kid,在拒絕它之前重新取得 JWKS 一次:輪換後,新令牌使用您快取的集合還沒有的金鑰簽署。

3

驗證簽發者

如果 iss 不完全是 ccr,則拒絕令牌。

4

根據您的環境驗證對象

aud 聲明是一個陣列。除非它包含您的環境 ID(形式為 ccpool_...),否則拒絕令牌。環境 ID 顯示在雲端環境管理頁面上您環境的詳細對話框中,並在任何環境的工作階段令牌中顯示為 ccr:pool_id 聲明。此檢查是將令牌範圍限制在您的環境並拒絕簽發給其他組織的令牌的內容。

5

驗證角色

如果 ccr:role 不完全是 session_worker,則拒絕令牌。為自託管環境簽發的其他令牌(例如環境祕密、執行者令牌和工作訂單)由相同的金鑰集簽署,但帶有不同的角色。

6

驗證過期

如果 exp 在過去,則拒絕令牌。Anthropic 預設簽發工作階段令牌的生命週期為四小時,最多八小時。執行者在過期前重新整理令牌,並將新值推送到工作階段,因此 Claude 在重新整理後啟動的子程序會繼承它。因此,一個工作階段在其生命週期內可以向您的服務呈現多個不同的有效令牌。

7

讀取身份

建立使用者的身份在 act 聲明中:act.sub 是他們的 Anthropic 使用者 ID,採用前綴形式 user:<id>,而 act.email(當建立表面記錄了一個時)是他們的電子郵件地址。您組織的服務身份建立的工作階段(包括 Claude Tag 頻道工作階段)改為在 act.sub 中帶有 agent: 主體,因此只有當 act.sub 帶有 user: 前綴時才將工作階段視為使用者建立的,而不是測試身份聲明是否不存在。請參閱聲明參考以了解完整結構和平面重複聲明。

這些檢查直接對應到標準 JWT 程式庫。下面的範例使用 jose 在 Node.js 中實現完整序列,它處理 JWKS 取得、快取和 kid 選擇,以及在 Python 中使用 PyJWT 及其內建 JWKS 用戶端。

import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
new URL("https://api.anthropic.com/v1/code/.well-known/jwks.json")
);

const PREFIX = "sk-ant-cc-";
const EXPECTED_POOL_ID = "ccpool_...";

export async function verifySessionToken(raw: string) {
if (!raw.startsWith(PREFIX)) {
throw new Error("not a self-hosted runner session token");
}
const jwt = raw.slice(PREFIX.length);

const { payload } = await jwtVerify(jwt, JWKS, {
issuer: "ccr",
audience: EXPECTED_POOL_ID,
algorithms: ["ES256"],
});

if (payload["ccr:role"] !== "session_worker") {
throw new Error("token is not a session_worker token");
}

const act = payload.act as { email?: string; sub?: string };
return {
sessionId: payload["ccr:session_id"] as string,
poolId: payload["ccr:pool_id"] as string,
orgId: payload["ccr:org_id"] as string,
creatorEmail: act?.email,
creatorSub: act?.sub,
};
}

在工作階段內驗證令牌

包裝指令碼在工作階段內執行,在 Claude 啟動之前。它們可以執行執行者二進位檔案的 self-hosted-runner decode-token 子命令,而不是呼叫 JWT 程式庫。子命令從位置引數、CLAUDE_CODE_SESSION_ACCESS_TOKEN 或管道 stdin 讀取令牌(按該順序),然後移除前綴、根據 JWKS 端點驗證簽名、檢查過期,並將聲明列印為 JSON。子命令僅執行簽名和過期檢查;它不檢查 iss、aud 或 ccr:role。當您的包裝器的驗證決定取決於這些聲明時,從列印的 JSON 讀取它們並明確比較它們。

此命令提取建立者身份,優先選擇 SSO 提供者的主體,然後是電子郵件地址,然後是建立者的 act.sub 主體 user:<id> 或 agent:<id>:

"$CLAUDE_RUNNER_CLAUDE_BIN" self-hosted-runner decode-token | jq -re '.act.attested_by.sub // .act.email // .act.sub'

包裝器在 CLAUDE_RUNNER_CLAUDE_BIN 中接收執行者自身二進位檔案的絕對路徑;使用該路徑而不是 PATH 解析的 claude,以便解碼在執行者本身使用的相同二進位檔案上執行。

使用 jq -re 而不是 jq -r,以便遺漏的聲明導致非零退出。僅使用 -r,遺漏的聲明會列印字面字串 null 並以零退出,這會無聲地將壞值傳遞到下游。僅當 JWKS 端點無法到達的離線檢查時,才將 --no-verify 傳遞給 decode-token。

聲明參考

下表列出了與驗證相關的工作階段令牌聲明。從 ccr:* 命名空間和 act 鏈讀取身份;平面 account_email、organization_uuid 和 account_uuid 聲明是可能被移除的向後相容性重複項。您組織的服務身份建立的工作階段(包括 Claude Tag 頻道工作階段)在 act.sub 中帶有 agent: 主體,並省略 act.email、ccr:account_id、account_email 和 account_uuid。兩個電子郵件聲明對於使用者建立的工作階段也是可選的:Anthropic 僅在建立請求的認證帶有電子郵件時才在工作階段建立時記錄它們,從 CLI 分派的工作階段可能兩者都缺少,因此根據 act.sub 或 ccr:account_id 而不是電子郵件來識別身份。令牌也可以帶有超出此表的其他聲明;忽略您不認識的聲明。

聲明 類型 描述
iss 字串 始終為 ccr。
sub 字串 ccr:session:<session_id>。
aud 字串陣列 始終包含 anthropic-api。對於自託管環境中的工作階段,陣列也包含您的環境 ID,例如 ccpool_...。驗證環境 ID,而不是 anthropic-api。
exp 數字 過期時間為 Unix 時間戳。四小時預設生命週期,八小時最大值。
iat 數字 簽發時間為 Unix 時間戳。
jti 字串 唯一令牌識別碼。
ccr:role 字串 對於工作階段令牌始終為 session_worker。
ccr:session_id 字串 工作階段 ID。與 sub 的後綴相同的值。
ccr:pool_id 字串 您的環境 ID。與出現在 aud 中的值相同。
ccr:org_id 字串 您的 Anthropic 組織 ID。
ccr:account_id 字串 建立使用者的 Anthropic 帳戶 ID:act.sub 的值,不帶 user: 前綴,一個標記的 user_... ID。與 spawn-runner hook 的 CLAUDE_RUNNER_ACCOUNT_ID 帶有的值相同,以及 --lock-to-account 接受的值,因此三者作為相等的字串進行比較。
account_email 字串 act.email 的重複;每當 act.email 不存在時就不存在。
organization_uuid 字串 您的 Anthropic 組織 UUID。
account_uuid 字串 建立使用者的 Anthropic 帳戶 UUID。
act 物件 RFC 8693 委派鏈。請參閱 The act chain。

The `act` chain

act 聲明記錄了從建立工作階段的使用者或服務身份到環境(其祕密允許執行者)以及建立該祕密的身份的完整委派路徑。建立者是最外層的參與者,因此 act.sub 直接識別他們。

路徑 描述
act.sub 建立使用者的 Anthropic 使用者 ID,形式為 user:<id>,或當您組織的服務身份建立工作階段時為 agent:<id>,就像它對 Claude Tag 頻道工作階段所做的那樣。
act.email 建立使用者的電子郵件地址,當在工作階段建立時記錄了一個時。不要要求它;根據 act.sub 識別。
act.attested_by 上游身份提供者對建立使用者的證明,當可用時。act.attested_by.sub 是您的 SSO 提供者(例如 Google 或 Okta)簽發的主體。在對應到您自己系統中的身份時,優先選擇這個而不是 act.email。
act.act 生成工作階段的執行者。act.act.sub 是 ccr:runner:<runner_id>。
act.act.act 環境。act.act.act.sub 是 ccr:pool:<pool_id>。
act.act.act.act 建立執行者註冊的環境祕密的身份。鏈在此結束。

範圍衍生認證

工作階段令牌識別建立工作階段的使用者或服務身份,但不要將其視為等同於該建立者直接登入。令牌位於工作階段內的環境變數中,因此 Claude 執行的任何程式碼以及工作階段啟動的任何工具或 MCP 伺服器都可以讀取並呈現它。

驗證也是離線的:根據 JWKS 驗證的令牌在其 exp 之前保持有效,無論自那時以來工作階段發生了什麼,Anthropic 不會為工作階段令牌發佈撤銷源。相應地綁定您從令牌衍生的任何內容。

當您的服務將令牌交換為內部認證時,簽發範圍限制在一個編碼工作階段應該到達的內容的認證:

  • 限制功能:授予工作階段編碼任務所需的資源的讀取和寫入存取權限,而不是建立者在其他地方持有的管理功能。
  • 限制生命週期:將衍生認證綁定到令牌的 exp 或更短。
  • 作為工作階段進行審計:記錄 ccr:session_id 和 jti 以及建立者身份,以便您可以將操作追蹤回特定工作階段。

建立者身份也以純環境變數的形式出現在兩個永遠不驗證令牌的表面上:

  • spawn-runner hook,在協調器上:hook 在任何執行者存在於佇列工作階段之前執行,並在 CLAUDE_RUNNER_ACCOUNT_EMAIL 和 CLAUDE_RUNNER_ACCOUNT_ID 等變數中接收建立者身份。協調器從工作訂單(授權生成一個執行者的簽署單次使用令牌)讀取它們,而不驗證工作訂單的簽名本身;聲明是受信任的,因為工作訂單通過協調器與 Anthropic 的連線到達,環境祕密對其進行驗證。
  • 包裝指令碼,在工作階段內:包裝器接收 CCR_SESSION_ACCOUNT_EMAIL,建立者的電子郵件從令牌預先提取,無需簽名驗證。該變數適合用於標籤,例如提交預告片,而不是用於驗證決定。

使用純變數進行協調器端決定,例如選擇機器映像。當下游服務需要獨立的密碼學證明而不是信任執行者的環境時,使用 CLAUDE_CODE_SESSION_ACCESS_TOKEN。

接下來