Делегированный доступ и on-behalf-of токены

Делегированный доступ и on-behalf-of (OBO) токены в архитектуре современных приложений используются для передачи прав пользователя через цепочку сервисов без утраты контекста исходной авторизации. В экосистеме JWT и спецификаций JOSE эта модель реализуется через криптографически защищённые токены, позволяющие сервисам действовать от имени пользователя, сохраняя при этом контроль над правами доступа и границами доверия.

Делегированный доступ предполагает, что один сервис получает право выполнять действия от имени пользователя в другом сервисе. При этом ключевой принцип заключается в том, что исходные пользовательские полномочия не заменяются сервисными, а аккуратно «протягиваются» через цепочку вызовов.

Типичный сценарий:

  • пользователь аутентифицируется в клиентском приложении
  • клиент обращается к API Gateway
  • gateway вызывает внутренний сервис
  • внутренний сервис вызывает другой сервис

Без механизма делегирования каждый этап потребовал бы повторной аутентификации или передачи слишком широких привилегий. OBO-токены решают эту проблему, сохраняя контекст пользователя.

OBO токены и принцип on-behalf-of

On-behalf-of токен — это разновидность access token, который содержит информацию о том, что запрос выполняется не напрямую пользователем, а сервисом от его имени.

Структурно OBO токен обычно включает:

  • идентификатор субъекта (sub) — пользователь
  • идентификатор клиента (client_id) — сервис, выполняющий запрос
  • аудиторию (aud) — целевой сервис
  • цепочку делегирования (иногда через claim act или azp)
  • срок действия (exp, iat)
  • scope — ограниченные права

Пример логики:

User -> Service A -> Service B
         |
         -> OBO token (User context preserved)

В отличие от обычного access token, OBO токен фиксирует факт промежуточного сервиса.

JOSE как криптографическая основа JWT

Библиотека Jose в JavaScript реализует спецификации JOSE:

  • JWS (JSON Web Signature) — подпись токенов
  • JWE (JSON Web Encryption) — шифрование токенов
  • JWK (JSON Web Key) — представление ключей
  • JWT (JSON Web Token) — прикладной формат

Основная задача JOSE — обеспечить:

  • целостность данных
  • проверку подлинности
  • возможность безопасного обмена между сервисами

В контексте OBO токенов наиболее важен JWS, так как именно подпись гарантирует, что делегирование не было подделано.

Формирование JWT через jose

Создание подписанного токена:

import { SignJWT } from 'jose'

const secret = new TextEncoder().encode('super-secret-key')

const token = await new SignJWT({
  sub: 'user_123',
  scope: 'read:messages',
  act: {
    sub: 'service_A'
  }
})
  .setProtectedHeader({ alg: 'HS256' })
  .setIssuedAt()
  .setExpirationTime('10m')
  .setAudience('service_B')
  .sign(secret)

Здесь ключевой момент — claim act, который отражает актор (сервис, действующий от имени пользователя). Это один из стандартных способов выражения OBO-цепочки.

Проверка токена и извлечение контекста

В сервисе-получателе токен необходимо проверить:

import { jwtVerify } from 'jose'

const secret = new TextEncoder().encode('super-secret-key')

const { payload } = await jwtVerify(token, secret, {
  audience: 'service_B'
})

console.log(payload.sub)   // user_123
console.log(payload.act)   // { sub: 'service_A' }

Проверка аудитории критически важна: она предотвращает использование токена вне предназначенного сервиса.

Механизм token exchange и OBO поток

В реальных системах OBO токен не создаётся произвольно. Он получается через процесс обмена токенов (token exchange), описанный в RFC 8693.

Схема:

  1. Клиент получает первичный access token
  2. Сервис A отправляет этот токен в authorization server
  3. Authorization server проверяет права
  4. Выдаётся новый токен для Service B с сохранением контекста пользователя

Пример логики запроса обмена:

POST /token
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=USER_TOKEN
requested_token_type=access_token
audience=service_B

Результат:

  • новый JWT
  • расширенные или ограниченные scope
  • сохранённый user context

Реализация OBO логики с jose

Библиотека jose не выполняет token exchange сама по себе, но используется для:

  • валидации входного токена
  • извлечения claims
  • формирования нового OBO токена

Пример цепочки:

1. Проверка входного токена

const userTokenPayload = await jwtVerify(userToken, publicKey)

2. Формирование нового токена от имени пользователя

const oboToken = await new SignJWT({
  sub: userTokenPayload.payload.sub,
  scope: 'read:messages',
  act: {
    sub: 'service_A'
  }
})
  .setProtectedHeader({ alg: 'RS256' })
  .setIssuedAt()
  .setExpirationTime('5m')
  .setAudience('service_B')
  .sign(privateKey)

Ключевое отличие — новый токен подписывается ключом текущего сервиса, но сохраняет пользовательский sub.

Делегирование и цепочка доверия

В сложных микросервисных системах OBO может формировать цепочку:

User → Service A → Service B → Service C

Каждый уровень добавляет свой контекст:

"act": {
  "sub": "service_B",
  "previous_act": {
    "sub": "service_A"
  }
}

Хотя стандарт не требует вложенных акторов, подобная модель используется в расширенных архитектурах.

Безопасность OBO токенов

Использование делегированного доступа требует строгого соблюдения правил:

Ограничение аудитории

Каждый токен должен быть привязан к конкретному сервису:

  • предотвращает replay-атаки
  • исключает горизонтальное использование токена

Короткий TTL

Время жизни OBO токенов обычно ограничено несколькими минутами:

  • снижает риск компрометации
  • заставляет регулярно обновлять контекст

Минимизация scope

Каждый последующий сервис должен получать только необходимые права:

  • принцип least privilege
  • предотвращение эскалации привилегий

Проверка цепочки делегирования

Сервис должен анализировать:

  • кто инициировал запрос
  • через какие сервисы он прошёл
  • допустима ли такая цепочка

Типичные архитектурные ошибки

В системах, использующих JOSE и OBO, часто встречаются следующие проблемы:

Потеря пользовательского контекста

Сервисы заменяют sub на свой идентификатор, что делает невозможным аудит действий пользователя.

Использование одного токена для всех сервисов

Это приводит к отсутствию сегментации доступа и нарушает модель доверия.

Отсутствие проверки audience

Игнорирование aud позволяет использовать токен вне его назначения.

Слишком широкие scope

Передача полного набора прав через всю цепочку увеличивает поверхность атаки.

Роль jose в построении доверенных цепочек

Jose в Node.js выступает фундаментальным инструментом для:

  • строгой криптографической подписи токенов
  • проверки целостности данных
  • управления ключами через JWK
  • поддержки различных алгоритмов (HS256, RS256, ES256)

Особенно важна возможность работы с асимметричными ключами:

  • приватный ключ подписывает OBO токены на стороне сервиса
  • публичный ключ используется для проверки в downstream сервисах

Это обеспечивает масштабируемую модель доверия между независимыми компонентами системы.

Практика микросервисного делегирования

В распределённых системах OBO токены часто комбинируются с:

  • API Gateway
  • Service Mesh (например, Istio)
  • централизованным Authorization Server

Типичный поток:

  1. Gateway валидирует user token
  2. Gateway формирует OBO token для внутреннего сервиса
  3. Сервисы пересылают OBO token дальше без изменения пользовательского контекста
  4. Каждый сервис проверяет подпись через jose

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

Расширенные claim-модели

Помимо sub и act, в OBO токенах часто используются:

  • azp — authorized party (первичный клиент)
  • scp — scopes
  • iat, exp — временные ограничения
  • iss — issuer
  • aud — аудитория

Комбинация этих полей позволяет точно описать происхождение запроса и уровень доверия.

Особенно важным становится поле iss, которое позволяет определить, какой сервис инициировал делегирование, что критично при анализе цепочек запросов в распределённых системах.

Криптографическая модель доверия

В основе jose лежит принцип:

  • токен не доверяется без проверки подписи
  • каждый сервис является независимым верификатором
  • доверие строится через ключи, а не через сетевую инфраструктуру

Это означает, что OBO токен безопасен только при строгом контроле ключей и алгоритмов подписи, а также корректной реализации проверки claims на каждом уровне системы