Аутентификация API: OAuth2, JWT, HMAC
TL;DR
OAuth2/OIDC + JWT — стандарт для клиентских приложений и серверных интеграций со сложной авторизацией (scopes/roles/tenants), SSO и короткими TTL токенов.
HMAC-подписи — лучший выбор для вебхуков и простых партнерских вызовов «сервер→сервер» с детерминированной проверкой и жесткой защитой от replay.
Усиливайте безопасность: mTLS или DPoP (sender-constrained tokens), короткие TTL (5–15 мин), ротация ключей (JWKS), refresh-токены с ротацией/anti-reuse, строгая валидация `aud/iss/exp/nbf/kid` и policy-as-code на gateway.
1) Карта решений: что где применять
2) OAuth2/OIDC: потоки и клиенты
2.1 Потоки
Authorization Code + PKCE (Web/Mobile): защищает код авторизации от перехвата.
Client Credentials: сервер↔сервер без пользователя; scopes — минимально необходимые.
Device Code: для устройств без браузера.
Refresh Token: только для доверенных клиентов; ротируйте и включайте reuse detection.
2.2 Клиентские типы
Confidential (серверы, BFF): хранят секреты; используйте mTLS.
Public (SPA/mobile): секрет хранить нельзя → PKCE, DPoP, короткие TTL и ограниченные scopes.
3) JWT: структура, сроки, верификация
3.1 Поля (claims)
Обязательные: `iss`, `sub`, `aud`, `exp`, `iat`, `nbf`, `jti`, `scope`/`permissions`, `tenant` (если мультиаренда), `kid`.
3.2 Сроки жизни
Access token: 5–15 минут.
Refresh token: дни/недели, ротируем при каждом обмене; при повторной подаче старого — блокируем сессию.
Clock skew: допуск ≤ 60 сек.
3.3 JWKS и ключи
Хранение ключей в KMS/Vault, `kid` обязателен.
Два активных ключа (rolling), перевыпуск раз в 60–90 дней или при инциденте.
Кэш JWKS на gateway ≤ 5 минут, с авто-инвалидацией.
3.4 Верификация на gateway/сервисах
Сверяйте: подпись, `aud` (допущенные сервисы), `iss`, `exp/nbf`, список блокировок (revocation).
Не доверяйте полям из тела без проверки подписи; игнорируйте `alg=none`.
Authorization: Bearer <JWT>
X-Trace-Id: <uuid>
4) Привязка токена к клиенту: mTLS, DPoP
mTLS (TLS клиентские сертификаты): токен выдается и валидируется только при наличии клиентского сертификата → токен бесполезен вне связки «ключ+сертификат».
DPoP (Demonstration of Proof-of-Possession): клиент подписывает каждый запрос одноразовым ключом → защита от replay и кражи токена в публичных клиентах.
Для критичных маршрутов (платежные мутации) — требовать один из механизмов.
5) Авторизация: scopes, roles, ABAC
Scopes — минимальные действия (`payments:write`, `payouts:status:read`).
Roles — агрегаты для админок; не используйте их напрямую без scopes.
ABAC — атрибуты в токене (`tenant`, `country`, `kyc_level`, `risk_flags`) → политики на gateway/OPA.
Политика на уровне маршрута/поля (GraphQL) и на уровне доменной операции (REST/gRPC).
6) HMAC-подписи: вебхуки и партнеры
6.1 Концепт
У каждой интеграции — собственный секрет.
Подпись над канонической строкой: `timestamp + "\n" + method + "\n" + path + "\n" + sha256(body)`
Заголовки:
X-Signature: v1=base64(hmac_sha256(secret, canonical_string))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF...
Окно времени: ≤ 300 сек; запросы с просроченным/будущим `X-Timestamp` отклонять.
Идемпотентность: храните `X-Event-Id` на TTL (24 ч) — отбрасывайте дубликаты.
6.2 Лучшие практики
Секреты в KMS/Vault, ротация каждые 90 дней.
Для публичных клиентов HMAC не подходит (секрет утекает); используйте OAuth2/DPoP.
7) Защита от replay, brute force и утечек
Nonce/`jti` для чувствительных операций; черный список использованных идентификаторов.
Rate/quotas: по ключу/клиенту/тенанту/маршруту; «дорогие» операции — отдельные квоты.
IP/ASN/Geo allow-lists для партнеров и вебхуков.
Content-type allow (`application/json`), лимит размера тела.
Маскирование PII в логах; запрет логировать токены/секреты.
8) Ошибки и ответы (единый формат)
Структура ошибки:json
{
"error": "invalid_token",
"error_description": "expired",
"trace_id": "4e3f-..."
}
Статусы:
- `401` — нет/невалидный токен (WWW-Authenticate).
- `403` — недостаточно прав (scope/ABAC).
- `429` — лимиты/квоты.
- gRPC: `UNAUTHENTICATED`/`PERMISSION_DENIED`/`RESOURCE_EXHAUSTED`.
9) Политики сроков и сессий
Access ≤ 15 мин; Refresh — ротация + reuse detection (подали старый — отзыв сессии).
Вебхуки HMAC: TTL подписи ≤ 5 мин; повторная доставка с экспоненциальным backoff.
Отзыв сессии/ключа → немедленное попадание в revocation list (кэш на gateway ≤ 1 мин).
10) Наблюдаемость и аудит
Корреляция по `trace_id`/`span_id`.
Метрики: auth success rate, `401/403/429`, латентность OIDC/JWKS, частота ротаций, reuse refresh, доля DPoP/mTLS трафика.
Аудит-лог: «кто, когда, с каким `sub/tenant/scope` вызвал что», изменения ключей/секретов, проваленные подписи HMAC.
11) Встраивание в API Gateway
JWT-валидация (JWKS кеш) и OPA/ABAC на шлюзе.
mTLS профили для доверенных клиентов/партнеров.
HMAC-верификация вебхуков на edge (до внутренних сервисов).
Rate/Quota полисы, circuit-breaker на OIDC-провайдера (кэшировать JWK).
Feature-flags: быстрое отключение клиента/ключа, смена алгоритма подписи.
12) Мини-сниппеты
Псевдо: верификация JWT
pseudo jwks = cache. getOrFetch(iss + "/.well-known/jwks. json")
key = jwks[kid]
assert verify_signature(jwt, key)
assert aud in ALLOWED_AUDIENCES and iss in TRUSTED_ISSUERS assert now in [nbf-60s, exp+60s]
Псевдо: проверка HMAC вебхука
pseudo canonical = timestamp + "\n" + method + "\n" + path + "\n" + sha256(body)
sig = base64(hmac_sha256(secret, canonical))
assert abs(now - timestamp) <= 300 assert not seen(event_id)
assert timingSafeEqual(sig, header["X-Signature"].split("v1=")[1])
markSeen(event_id, ttl=86400)
Пример scope-политики (OPA/Rego идея)
rego allow {
input. jwt. scope[_] == "payments:write"
input. jwt. tenant == input. route. tenant
}
13) Плейбуки инцидентов
Утечка приватного ключа/JWT-подписанта: перевыпуск ключей, обновление JWKS, немедленное отключение старого (`kid` → deny), инвалидация refresh, принудительный logout.
Подмена вебхуков: ротация секретов, IP allow-list, усиление окна `X-Timestamp`, повторная доставка пропущенных событий.
Replay/брутфорс: включить DPoP/mTLS на критичных маршрутах, сужение квот, временные блоки по IP/ASN, включить `jti`-блоклист.
Outage OIDC: деградация кэшированных токенов (grace), circuit-breaker провайдера, уведомление клиентов.
14) Чек-листы внедрения
Аутентификация (минимум):- OAuth2: Code+PKCE (Web/Mobile), Client Credentials (server-to-server)
- TTL: Access ≤ 15 мин, Refresh с ротацией и reuse detection
- JWKS: два активных ключа, `kid`, кэш ≤ 5 мин
- Вебхуки: HMAC v1, `X-Timestamp`, `X-Event-Id`, окно ≤ 300 сек, идемпотентность
- Sender-constrained: mTLS/DPoP на критичных маршрутах
- ABAC/OPA: scopes+tenant/risk в политиках шлюза
- Rate/Quota и 429; IP/ASN allow-lists для партнеров
- Аудит и алерты (401/403/429, reuse refresh, подписи HMAC)
- Не логировать токены/секреты/полные тела карт
- Маскирование PII; DSAR поддержка; срок хранения логов ограничен
15) Анти-паттерны
`alg=none` или доверие токену без проверки подписи/JWKS.
Долгоживущие access-токены (часы/сутки).
Один общий HMAC-секрет на всех партнеров.
Вебхуки без таймштампа/идемпотентности.
Refresh-токены без ротации и без reuse detection.
Отсутствие `aud`/`iss`-валидации и `kid`-ротации.
Хранение секретов в переменных окружения без KMS/Vault.
16) НФТ/SLO (ориентиры)
OIDC/JWKS доступность ≥ 99.95% (edge-кэш снижает зависимость).
JWT валидация добавка на gateway ≤ 2–5 мс p95.
Ошибки аутентификации (`401`) ≤ 0.5% от общего трафика (без учета ботов).
Подписанные вебхуки: доля успешно верифицированных ≥ 99.9%, средняя задержка доставки ≤ 3 с.
Резюме
Комбинируйте механизмы: OAuth2/OIDC + JWT для пользователей и богатых серверных сценариев, HMAC для вебхуков/простых партнеров, а для критичных операций — mTLS/DPoP. Держите короткие TTL, ротации ключей (JWKS), строгие политики ABAC/OPA, защищайте контуры от replay и утечек, и автоматизируйте все на уровне API Gateway. Так аутентификация станет предсказуемой, масштабируемой и безопасной — без компромиссов для UX и монетизации.