SpyBara
Go Premium

self-hosted-environments-identity.md 2026-09-11 23:01 UTC to 2026-09-12 03:02 UTC

This page contains 270 additions and 0 deletions.

2026
Sat 12 03:02

Проверка идентификации сеанса в самостоятельно размещаемых окружениях

Проверьте JWT CLAUDE_CODE_SESSION_ACCESS_TOKEN, чтобы сервисы в вашей сети могли доверять запросам от сеансов в вашем самостоятельно размещаемом окружении.

Самостоятельно размещаемое окружение позволяет сеансам Claude Code в веб-интерфейсе работать на инфраструктуре, которой вы управляете, вместо инфраструктуры Anthropic. Поскольку сеанс работает внутри вашей сети, Claude может напрямую вызывать ваши внутренние сервисы. Эти сервисы должны иметь способ подтвердить, что запрос поступил от сеанса Claude Code в вашем окружении, и определить идентификацию пользователя или сервиса, который создал этот сеанс.

Каждый сеанс в самостоятельно размещаемом окружении получает подписанный JSON Web Token (JWT) в переменной окружения CLAUDE_CODE_SESSION_ACCESS_TOKEN. Сеанс представляет токен как любые учетные данные носителя; например, скрипт, который запускает Claude, может вызвать ваш сервис с помощью curl -H "Authorization: Bearer $CLAUDE_CODE_SESSION_ACCESS_TOKEN". Anthropic подписывает токен и публикует ключи проверки на публичной конечной точке JWKS. Ваши сервисы получают эти ключи, проверяют подпись и читают утверждения, чтобы решить, какой доступ предоставить.

Токен сеанса

Прежде чем писать код проверки, знайте, что устанавливает токен и какую форму будет иметь ваша библиотека JWT.

Что доказывает токен

Действительный токен устанавливает некоторые факты и намеренно не устанавливает другие:

  • Доказывает: Anthropic выдала токен для конкретного сеанса в конкретном окружении и как был создан сеанс: пользователем в вашей организации или идентификацией сервиса вашей организации, что является способом запуска сеансов канала Claude Tag
  • Не доказывает: какой процесс на хосте runner представляет его. Токен находится в переменной окружения внутри сеанса, поэтому любой код, который запускает Claude, и любой инструмент или MCP сервер, который запускает сеанс, могут его прочитать и представить.

Два следствия для ваших сервисов:

  • Проверьте утверждение aud против вашего ID окружения, значения ccpool_..., показанного с вашим окружением на странице администратора Cloud environments, чтобы отклонить токены, выданные для любого другого окружения организации.
  • Ограничьте учетные данные, которые вы получаете из токена, тем, что может делать один сеанс кодирования, а не всем, что может делать создатель сеанса. См. Ограничение полученных учетных данных.

Формат токена

Значение 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, который является ECDSA на кривой P-256 с SHA-256. Заголовок токена содержит kid, который идентифицирует, какой ключ в JWKS его подписал.

Проверка токена

Проверка выполняется в одном из двух мест. Сервисы в вашей сети проверяют токен криптографически против опубликованных ключей Anthropic, а скрипты-обертки внутри сеанса могут использовать встроенный декодер бинарного файла runner.

Проверка токена из вашего сервиса

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 окружения показан в диалоговом окне деталей вашего окружения на странице администратора Cloud environments и отображается как утверждение ccr:pool_id в любых токенах сеанса окружения. Эта проверка — это то, что ограничивает токен вашим окружением и отклоняет токены, выданные другим организациям.

5

Проверьте роль

Отклоните токен, если ccr:role не является ровно session_worker. Другие токены, выданные для самостоятельно размещаемых окружений, такие как секреты окружения, токены runner и рабочие заказы, подписаны тем же набором ключей, но имеют разные роли.

6

Проверьте срок действия

Отклоните токен, если exp находится в прошлом. Anthropic выдает токены сеанса с четырехчасовым сроком действия по умолчанию и максимум восемь часов. Runner обновляет токен перед истечением срока и отправляет новое значение в сеанс, поэтому подпроцессы, которые Claude запускает после обновления, наследуют его. Таким образом, один сеанс может представить несколько различных действительных токенов вашему сервису в течение его жизни.

7

Прочитайте идентификацию

Идентификация создающего пользователя находится в утверждении act: act.sub — это его ID пользователя Anthropic в префиксной форме user:<id>, а act.email, когда создающая поверхность записала его, — это его адрес электронной почты. Сеансы, которые создает идентификация сервиса вашей организации, включая сеансы канала Claude Tag, вместо этого содержат субъект agent:, поэтому рассматривайте сеанс как созданный пользователем только когда act.sub содержит префикс user:, а не проверяя, отсутствуют ли утверждения идентификации. См. справочник утверждений для полной структуры и плоских дублирующихся утверждений.

Проверки напрямую соответствуют стандартным библиотекам JWT. Примеры ниже реализуют полную последовательность в Node.js с jose, которая обрабатывает получение 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. Вместо вызова библиотеки JWT они могут запустить подкоманду self-hosted-runner decode-token бинарного файла runner. Подкоманда читает токен из позиционного аргумента, из 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'

Обертки получают абсолютный путь к собственному бинарному файлу runner в CLAUDE_RUNNER_CLAUDE_BIN; используйте этот путь вместо разрешенного PATH claude, чтобы декодирование выполнялось на том же бинарном файле, который использует сам runner.

Используйте jq -re вместо jq -r, чтобы отсутствующее утверждение вызвало ненулевой выход. С одним -r, отсутствующее утверждение выводит буквальную строку null и выходит с нулем, что молча передает плохое значение вниз по потоку. Передайте --no-verify в decode-token только для автономной проверки, где конечная точка JWKS недоступна.

Справочник утверждений

Таблица ниже перечисляет утверждения токена сеанса, релевантные для проверки. Читайте идентификацию из пространства имен ccr:* и цепи act; плоские утверждения account_email, organization_uuid и account_uuid — это дубликаты обратной совместимости, которые могут быть удалены. Сеансы, которые создает идентификация сервиса вашей организации, включая сеансы канала Claude Tag, содержат субъект agent: в act.sub и опускают act.email, ccr:account_id, account_email и account_uuid. Два утверждения электронной почты также опциональны для сеансов, созданных пользователем: Anthropic записывает их при создании сеанса только когда учетные данные создающего запроса содержат электронную почту, и сеанс, отправленный из CLI, может не иметь обоих, поэтому ключевая идентификация на act.sub или ccr:account_id вместо электронной почты. Токены также могут содержать дополнительные утверждения помимо этой таблицы; игнорируйте утверждения, которые вы не узнаете.

Утверждение Тип Описание
iss string Всегда ccr.
sub string ccr:session:<session_id>.
aud array of strings Всегда содержит anthropic-api. Для сеансов в самостоятельно размещаемых окружениях массив также содержит ваш ID окружения, такой как ccpool_.... Проверьте ID окружения, а не anthropic-api.
exp number Срок действия как временная метка Unix. Четырехчасовой срок действия по умолчанию, максимум восемь часов.
iat number Выданный как временная метка Unix.
jti string Уникальный идентификатор токена.
ccr:role string Всегда session_worker для токенов сеанса.
ccr:session_id string ID сеанса. То же значение, что и суффикс sub.
ccr:pool_id string Ваш ID окружения. То же значение, которое отображается в aud.
ccr:org_id string Ваш ID организации Anthropic.
ccr:account_id string ID учетной записи Anthropic создающего пользователя: значение act.sub без префикса user:, помеченный ID user_.... То же значение, которое несет CLAUDE_RUNNER_ACCOUNT_ID хука spawn-runner и принимает --lock-to-account, поэтому все три сравниваются как равные строки.
account_email string Дубликат act.email; отсутствует всякий раз, когда отсутствует act.email.
organization_uuid string Ваш UUID организации Anthropic.
account_uuid string UUID учетной записи Anthropic создающего пользователя.
act object Цепь делегирования RFC 8693. См. Цепь act.

Цепь `act`

Утверждение act записывает полный путь делегирования от идентификации пользователя или сервиса, который создал сеанс, вниз к окружению, чей секрет допустил runner, и идентификации, которая создала этот секрет. Создатель — это самый внешний актор, поэтому act.sub идентифицирует его напрямую.

Путь Описание
act.sub ID пользователя Anthropic создающего пользователя в форме user:<id> или agent:<id>, когда идентификация сервиса вашей организации создала сеанс, как это происходит для сеансов канала Claude Tag.
act.email Адрес электронной почты создающего пользователя, когда он был записан при создании сеанса. Не требуйте его; ключевая идентификация на act.sub.
act.attested_by Аттестация поставщика идентификации вышестоящего уровня для создающего пользователя, когда доступна. act.attested_by.sub — это субъект, выданный вашим поставщиком SSO, таким как Google или Okta. Предпочитайте это act.email при сопоставлении с идентификациями в ваших собственных системах.
act.act Runner, который запустил сеанс. act.act.sub — это ccr:runner:<runner_id>.
act.act.act Окружение. act.act.act.sub — это ccr:pool:<pool_id>.
act.act.act.act Идентификация, которая создала секрет окружения, с которым runner зарегистрировался. Цепь заканчивается здесь.

Ограничение полученных учетных данных

Токен сеанса идентифицирует пользователя или идентификацию сервиса, который создал сеанс, но не рассматривайте его как эквивалент этого создателя, входящего напрямую. Токен находится в переменной окружения внутри сеанса, поэтому любой код, который запускает Claude, и любой инструмент или MCP сервер, который запускает сеанс, могут его прочитать и представить.

Проверка также автономна: токен, который проверяется против JWKS, остается действительным до его exp, независимо от того, что произошло с сеансом с тех пор, и Anthropic не публикует канал отзыва для токенов сеанса. Привяжите все, что вы получаете из токена, соответственно.

Когда ваш сервис обменивает токен на внутренние учетные данные, выдайте учетные данные, ограниченные тем, что один сеанс кодирования должен достичь:

  • Ограничьте возможности: предоставьте доступ на чтение и запись к ресурсам, которые сеансу нужны для задач кодирования, а не административные возможности, которые создатель имеет в другом месте.
  • Ограничьте время жизни: привяжите полученные учетные данные к exp токена или короче.
  • Аудит как сеанс: запишите ccr:session_id и jti рядом с идентификацией создателя, чтобы вы могли отследить действия обратно к конкретному сеансу.

Идентификация создателя также отображается в простых переменных окружения на двух поверхностях, которые никогда не проверяют токен:

  • Хук spawn-runner, на оркестраторе: хук работает перед тем, как для поставленного в очередь сеанса существует какой-либо runner, и получает идентификацию создателя в переменных, таких как CLAUDE_RUNNER_ACCOUNT_EMAIL и CLAUDE_RUNNER_ACCOUNT_ID. Оркестратор читает их из рабочего заказа, подписанного одноразового токена, который авторизует запуск одного runner, без проверки подписи самого рабочего заказа; утверждения доверяются, потому что рабочий заказ поступает через соединение оркестратора с Anthropic, которое аутентифицирует секрет окружения.
  • Скрипты-обертки, внутри сеанса: обертки получают CCR_SESSION_ACCOUNT_EMAIL, адрес электронной почты создателя, предварительно извлеченный из токена без проверки подписи. Переменная подходит для маркировки, такой как трейлеры коммитов, а не для решений об аутентификации.

Используйте простые переменные для решений на стороне оркестратора, таких как выбор образа машины. Используйте CLAUDE_CODE_SESSION_ACCESS_TOKEN, когда нижестоящему сервису нужно независимое криптографическое доказательство вместо доверия окружению runner.

Что дальше