ГлавнаяБлогID-JAG: авторизация AI-агентов через обмен токенами
Алгоритмы

ID-JAG: авторизация AI-агентов через обмен токенами

ID-JAG — механизм авторизации AI-агентов, использующий обмен токенами (RFC 8693, RFC 7523) для безопасного делегирования прав. Узнайте, как внедрить принцип наименьших привилегий в цепочке вызовов агентов.

Al
Редакция Algolitalgolit.ru
10 мин чтения28 июля 2026 г.

Что такое ID-JAG и зачем он нужен?

Представьте: AI-агент, подключённый к внутренним системам, получает права наравне с человеком. Одна ошибка — и последствия могут быть катастрофическими. ID-JAG (Identity Assertion JWT Authorization Grant) решает именно эту проблему: он позволяет агенту действовать от имени пользователя, но с минимально необходимыми правами и строгим аудитом.

ID-JAG — это механизм авторизации, при котором каждый вызов API сопровождается доказательством: «конкретный пользователь в конкретный момент разрешил агенту выполнить это действие». Он основан на двух RFC — обмене токенами (RFC 8693) и JWT Bearer (RFC 7523) — и уже реализован в системах Athenz и Okta, а также цитируется в спецификации MCP.

От OAuth2 и PKCE к новым вызовам эпохи агентов

Ранее мы разбирали OAuth2 PKCE — он защищает клиентское приложение от перехвата кода авторизации. Но PKCE решает проблему одношаговой аутентификации «пользователь → приложение». ID-JAG же работает в многошаговой цепочке: пользователь → шлюз AI → MCP-сервер → ресурсный сервер. Каждый шаг требует доказательства полномочий, и ID-JAG позволяет обменивать токены с сужением прав на каждой границе доверия.

В отличие от PKCE, ID-JAG не требует всплывающих окон для каждого нового сервиса: авторизация консолидируется при входе через SSO, а затем агент использует выпущенный identity assertion для получения токенов без участия пользователя.

Два краеугольных RFC: Token Exchange и JWT Bearer

RFC 8693 — OAuth 2.0 Token Exchange

Определяет протокол обмена одного токена на другой. Пример запроса:

POST /token
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=<Identity Assertion JWT>
subject_token_type=urn:ietf:params:oauth:token-type:jwt
requested_token_type=urn:ietf:params:oauth:token-type:access_token
scope=read:orders

Параметр subject_token содержит делегируемый токен, requested_token_type — желаемый тип, а scope позволяет сузить права прямо при обмене.

RFC 7523 — JWT Bearer Grant

Позволяет использовать JWT напрямую как учётные данные OAuth2 без дополнительного обмена:

POST /token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=<Signed Identity Assertion JWT>

Сервер авторизации проверяет подпись JWT с помощью публичного ключа IdP и, если поля aud, scope, exp корректны, выдаёт Access Token без повторного согласия пользователя.

Identity Assertion JWT обычно содержит:

{
  "iss": "https://enterprise.idp.example.com/v1",
  "sub": "alice@company.com",
  "aud": "https://api.service.example.com",
  "exp": 1773839486,
  "iat": 1773825086,
  "jti": "abc123-7dc6-42ab-b326-uniqueid",
  "scope": "read:orders write:tickets"
}

Поле jti — уникальный идентификатор для предотвращения повторного использования.

Полный поток обмена токенами ID-JAG

Рассмотрим архитектуру из туториала id-jag-the-hard-way (Athenz как сервер авторизации):

  1. Пользователь входит в IdP (Keycloak) и получает OIDC ID Token.
  2. Шлюз AI обменивает ID Token на ID-JAG через RFC 8693 (grant_type=token-exchange).
  3. Затем по RFC 7523 обменивает ID-JAG на Athenz Access Token (grant_type=jwt-bearer).
  4. Шлюз вызывает MCP-сервер с этим Access Token.
  5. MCP-сервер самостоятельно выполняет Token Exchange (RFC 8693), используя свой mTLS-сертификат, и получает новый Access Token с минимальным скоупом для данного инструмента.
  6. С этим суженным токеном MCP-сервер вызывает финальный ресурсный сервер.

На каждом шаге токен обменивается, а его область действия сужается. Токен шлюза не может быть использован напрямую для доступа к ресурсному серверу — MCP-сервер принудительно перевыпускает его. В итоговом токене фиксируются и sub (пользователь), и act (агент), что сохраняет полную цепочку аудита.

Принцип наименьших привилегий на каждом шаге

Самое красивое в ID-JAG — что наименьшие привилегии реализуются архитектурно, а не через code review. Рассмотрим пример из моей реализации id-jag-mcp на Go:

ИнструментAthenz Scope
get_k8s_docsapi:role.docs-getter
delete_k8s_docapi:role.docs-deleter
post_k8s_docapi:role.docs-poster

Когда MCP-сервер получает запрос, он не передаёт токен шлюза напрямую — он всегда запрашивает у Athenz ZTS новый токен ровно с тем скоупом, который нужен для данного инструмента. Даже если токен шлюза содержит права на чтение и удаление, MCP-сервер запросит только api:role.docs-getter для чтения. Это делает нарушение принципа наименьших привилегий архитектурно невозможным.

Почему я переписал MCP-сервер на Go?

Исходный MCP-сервер в id-jag-the-hard-way был написан на TypeScript + Express с самописным JSON-RPC 2.0. Я хотел проверить две вещи: воспроизводима ли логика обмена токенов на другом языке и как работает официальный modelcontextprotocol/go-sdk. В результате я полностью заменил протокольный слой на Go SDK, сохранив ту же логику маппинга скоупов и mTLS-обмена. mTLS-клиент написан с нуля, без зависимости от официального Go-клиента Athenz.

Практический вывод

Попробуйте развернуть мою реализацию id-jag-mcp из репозитория kkdai/id-jag-mcp. Это поможет вам понять, как работает обмен токенов на практике и как внедрить принцип наименьших привилегий в ваши AI-агенты. Начните с запуска тестового окружения с Athenz и Keycloak, затем поэкспериментируйте с вызовом разных инструментов — вы увидите, как сужаются права на каждом шаге.

#ID-JAG#авторизация#обмен токенами#AI-агенты#принцип наименьших привилегий
Al
Редакция Algolit

Пишем про алгоритмы, подготовку к собеседованиям и карьеру в IT — так, чтобы было понятно и полезно.

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →