ID-JAG: как ограничить права агента в цепочке MCP

Соло-разработчик, который подключает агента к внутренним API через MCP, рискует выдать программе слишком широкий доступ: один долгоживущий ключ или проброс пользовательского токена — и prompt injection превращается в операцию от вашего имени. В заметках инженер evanlin разбирает ID-JAG — черновик IETF для делегированной авторизации агентов, на который уже ссылается спецификация MCP; параллельно он переносит учебный MCP-сервер с TypeScript на Go и официальный modelcontextprotocol/go-sdk.
Почему агентам нужна отдельная модель доверия
За последние полгода в инженерных обсуждениях всё чаще фигурирует прямое подключение AI-агентов к внутренним системам — не как демо-чат, а как цепочка вызовов к API. Классический OAuth для браузерного клиента не закрывает сценарий, где между пользователем и ресурсом стоят шлюз, MCP Server и, возможно, субагенты оркестратора.
Каждый новый хоп умножает поверхность атаки: если на каком-то этапе токен слишком широкий или живёт слишком долго, утечка бьёт по учётной записи человека, а не по анонимному сервису.
Автор связывает появление ID-JAG с этой волной и отмечает, что механизм уже попал на страницу OAuth.net в разделе Cross-App Access (XAA) — как ответ на проблему эпохи агентов, а не как косметику к существующему login flow.
ID-JAG: Identity Assertion JWT Authorization Grant
ID-JAG расшифровывается как Identity Assertion JWT Authorization Grant. Это способ доказать, что конкретный пользователь в конкретный момент разрешил агенту выполнить конкретную операцию — с узким scope и коротким сроком жизни assertion.
На момент публикации материала ID-JAG остаётся Internet-Draft IETF, а не финальным RFC. При этом LY Corporation (стек авторизации Athenz) и Okta уже начали реализацию, а в спецификации MCP (Model Context Protocol) есть отсылка к этому черновику.
Механизм опирается на два стандарта:
- RFC 8693 — OAuth 2.0 Token Exchange;
- RFC 7523 — JWT Bearer Grant.
Identity Assertion JWT несёт поля iss, sub, aud, exp, iat, jti, scope; jti нужен, чтобы срезать replay. Итоговый access token фиксирует и sub (от чьего имени действуют), и act (какой агент выполняет операцию) — аудит не обрывается на границе «человек одолжил сессию программе».
Цепочка: от IdP до MCP Server
Типовая архитектура, которую описывает автор, выглядит так:
User → IdP (Keycloak) → AI Client Gateway → MCP Server → Resource Server
Если Orchestrator Agent вызывает Sub-Agent, риск «передаётся вниз» по цепочке — без явной модели делегирования каждый уровень может расширить права.
Полный token exchange flow на примере tutorial-стека Athenz:
- Пользователь логинится в IdP (Keycloak) и получает OIDC ID Token.
- AI Client Gateway по RFC 8693 обменивает ID Token на ID-JAG (
grant_type=token-exchange,requested_token_type=id-jag). - По RFC 7523 ID-JAG превращается в Athenz Access Token (
grant_type=jwt-bearer,assertion=<ID-JAG>). - AI Client вызывает MCP Server с этим access token.
- MCP Server выполняет собственный RFC 8693 Token Exchange: меняет входящий токен на access token с минимальным scope для конкретного tool — через mTLS service identity сервера, а не через учётные данные пользователя.
- Resource Server получает уже downscoped token.
UX-выгода: вместо повторных browser popup на каждый новый сервис авторизация консолидируется в момент SSO-логина; дальше агент обменивает уже выданное identity assertion на токен через authorization server.
Угрозы, которые автор выделяет для агентов
В тексте перечислены три класса риска — все привязаны к тому, как агент ходит во внутренние системы:
- prompt injection и галлюцинации — агент инициирует операции, которых пользователь не задумывал;
- слишком широкие права — общий API key, service account или долгоживущий пользовательский токен; при утечке злоумышленник полностью выдаёт себя за пользователя;
- отсутствие аудита, когда сессия человека «одолжена» программе без фиксации
act.
ID-JAG не отменяет инъекции в промпт, но сужает blast radius: даже если агент «сошёл с ума», токен на конкретный tool живёт недолго и несёт минимальный scope.
PKCE и ID-JAG — разные задачи. PKCE защищает доверие к публичному клиенту в одном хопе (
code_verifier/code_challenge). ID-JAG квалифицирует нечеловеческую service identity, действующую от имени человека, в цепочке из нескольких хопов. Механизмы не конфликтуют — они работают на разных этапах.
Go-реализация MCP-сервера и официальный SDK
Автор пере-реализовал MCP Server из tutorial-репозитория athenz-community/id-jag-the-hard-way на Go: проект kkdai/id-jag-mcp (лицензия Apache 2.0). Мотивация двойная: проверить, что token-exchange архитектура воспроизводима на другом языке, и оценить официальный modelcontextprotocol/go-sdk.
Оригинал (api_server/mcp/) — TypeScript + Express с hand-coded JSON-RPC 2.0 без официального SDK. Go-версия сохраняет ту же логику (scope mapping, mTLS token exchange flow), но протокольный слой заменён на SDK; mTLS-клиент написан вручную, без Athenz Go client library.
| Путь | Назначение |
|---|---|
cmd/id-jag-mcp/ |
Точка входа, сборка компонентов, HTTP server |
internal/config/ |
Конфигурация из env |
internal/athenz/ |
mTLS client + Athenz ZTS RFC 8693 token exchange |
internal/tools/ |
Типы входов инструментов и общая логика upstream |
internal/server/ |
Регистрация MCP tools (official SDK), REST shortcuts, логирование |
Три MCP-инструмента и соответствующие Athenz scope:
| Tool | Athenz Scope |
|---|---|
get_k8s_docs |
api:role.docs-getter |
delete_k8s_doc |
api:role.docs-deleter |
post_k8s_doc |
api:role.docs-poster |
Ключевой паттерн для соло-разработчика с агентом: MCP Server не форвардит входящий access token напрямую в upstream. Он использует собственный mTLS-сертификат для token exchange с Athenz ZTS и запрашивает scope, нужный конкретному tool — principle of least privilege на каждом вызове.
Запуск требует mTLS-сертификаты, доступный Athenz ZTS и upstream API; конфигурация через env (UPSTREAM_BASE_URL, AUTHORIZATION_SERVER_URL и др.). Эндпоинты: /mcp для MCP-клиентов плюс REST shortcuts для curl-тестов. Тесты (go test ./...) используют httptest для симуляции ZTS и upstream без реального Athenz/Keycloak.
Что вынести в соло-workflow с агентом и MCP
Если вы собираете агента поверх MCP и внутренних API, практический чеклист из материала сводится к архитектуре, а не к выбору модели:
- Не пробрасывайте пользовательский токен сквозь MCP Server — сервер должен иметь собственную service identity и обменивать токен на downscoped scope под конкретный tool.
- Разделяйте tools по scope — как в примере с
docs-getter,docs-deleter,docs-poster: агент не должен получать delete, если задача — только чтение. - Следите за цепочкой субагентов — делегирование вниз без ID-JAG-подобной модели умножает риск широких прав.
- Для Go-стека имеет смысл смотреть на официальный
modelcontextprotocol/go-sdkвместо самописного JSON-RPC — автор как раз этим и мотивировал перенос.
Материал опубликован 28 июля 2026 года; оценочное время чтения оригинала — около 10 минут. Это learning notes, а не продакшен-гайд: перед внедрением в свой MCP-контур стоит свериться с актуальной версией Internet-Draft и политикой вашего authorization server.
Источники
- Learning Notes: Authorization Challenges in the AI Agent Era — ID-JAG and Go re-implementation — evanlin, Dev.to, 28 июля 2026 (в тексте также упомянуты репозитории
athenz-community/id-jag-the-hard-wayиkkdai/id-jag-mcp)