Безопасность API и токены
Краткое резюме
Безопасность API — это совокупность механизмов аутентификации, авторизации, криптографической защиты, анти-злоупотреблений и наблюдаемости, которая обеспечивает, что запрос выполняет ожидаемый субъект к ожидаемому ресурсу в ожидаемом контексте. Ключевой артефакт — токен (или подпись запроса), доказывающий право на вызов. Хорошая архитектура опирается на короткоживущие токены, четкие скоупы, минимальные привилегии, защиту от повторов, rate limiting и операционные процедуры (ротации, аудит, инциденты).
Модели аутентификации API: когда и что выбирать
API-ключ (статический секрет)
Простой для B2B-интеграций и низкорисковых сценариев. Не несет контекста, требует хранения на стороне сервиса.
Используйте только с IP/ASN allow-list, фиксированными квотами, коротким TTL и ротациями.
OAuth 2.1 / OIDC
Стандарт для пользовательских и партнерских интеграций: access token (краткоживущий) + refresh token (ротация) + скоупы.
Public-клиенты — с PKCE; confidential-клиенты — с клиентским секретом/mTLS.
Client Credentials (m2m)
Машина→машина: access token для сервисов по строго заданным скоупам и audience, часто без refresh (получение заново).
mTLS (взаимный TLS)
Привязывает идентичность к каналу. Идеально для высокорисковых или платежных интеграций (PoP поверх TLS).
Может совмещаться с OAuth (токены только по mTLS-клиентам).
Подписи запросов (HMAC/EdDSA)
Когда нужен независимый от транспорта PoP: заголовок подписи, timestamp и nonce. Удобно для вебхуков и оффлайн-проверки.
Форматы и типы токенов
JWT (JWS, подписанные)
Самодостаточные, проверяются локально; обязательны `iss`, `sub`, `aud`, `exp`, `iat`, `jti`, `scope`.
Риск — отзыв сложнее: используйте короткие TTL (5–15 мин) + список отозванных `jti` при инцидентах.
JWE (зашифрованные JWT)
Нужны, если payload чувствительный (PII). Стоимость — выше сложность и накладные расходы.
Reference tokens
Непрозрачные идентификаторы, проверяются через introspection у Authorization Server — проще отзыв/централизация.
PoP/DPoP
Привязка токена к ключу клиента или к TLS-сессии, снижает ценность украденного токена.
Содержимое токена: минимально достаточно
Рекомендуемые клеймы (JWT):- `iss` (issuer), `sub` (subject), `aud` (целевая система/ресурс), `exp` (срок), `iat`, `nbf` (опционально), `jti`.
- `scope`/`permissions` (минимально необходимые), `tenant` (для многотенантных), `device_compliant`/`amr` (метод аутентификации), `ip`/`asn` (если применимо к политике).
- Короткие TTL для access (5–15 мин), refresh — 12–48 ч (с вращающейся ротацией).
- Аудитория (`aud`) — строго конкретный ресурс, иначе токен «многоразовый».
- Скоупы — действие и объект (например, `payments:withdraw.read`).
- Размер — ≤ 2–4 KB для заголовков и прокси; иначе возможны проблемы с гейтвеями.
Авторизация и политики
RBAC+ABAC: роль + контекст (организация, гео, риск, состояние устройства).
PEP/PDP: проверка токена и принятие решения на API-шлюзе/прокси (Envoy/OPA) до приложения.
Декларативные правила: хранить в Git, проходить policy-tests в CI.
rego package policy. withdraw
default allow = false
allow {
input. token. aud == "wallet-api"
input. token. scope[_] == "payments:withdraw. create"
input. device. compliant == true input. risk. score < 70
}
Подпись запросов (HMAC) и анти-replay
Когда нужно: вебхуки, интеграции без OAuth, двойная проверка критичных операций.
Схема заголовков (пример):
X-Client-Id: <id>
X-Timestamp: 2025-11-05T13:20:10Z
X-Nonce: 4d1f...a2
X-Signature: base64(HMAC_SHA256(secret, method + "\n" + path + "\n" + sha256(body) + "\n" + timestamp + "\n" + nonce))
Правила:
- Отклонять запросы с рассинхроном времени > ±300 с.
- Nonce хранить 5–15 мин и не принимать повторы (replay-кэш).
- Подписывать канонизированное представление запроса (метод, путь, query, хэш тела).
Идемпотентность и транзакционная защита
Idempotency-Key для операций списания/выплаты/создания: одинаковый ключ → один и тот же эффект.
Срок жизни ключа — ≥ время бизнес-таймаута (обычно 24–72 ч).
Логика на стороне сервера: сравнить параметры запроса с ранее зафиксированными для этого ключа.
Браузерные и мобильные клиенты
PKCE обязательно (public-клиенты).
Refresh-токен в браузере — избегать; если нужен — ROTATION + реагирование на повтор (replay-детект).
Хранение: session storage > local storage; лучше — за токены отвечает backend for frontend (BFF).
SameSite, Secure, HttpOnly для cookie; CORS — явные allow-lists, заголовки и методы; preflight-кешировать безопасно.
m2m и высокорискованные интеграции
mTLS + OAuth2 Client Credentials с скоупами и `aud`.
IP/ASN allow-list на гейтвее.
PoP/DPoP или HMAC-подписи поверх TLS для критичных операций.
Квоты и rate limits на организацию/клиента/ключ.
Ротации, отозвы и реагирование на инциденты
Ротация секретов и ключей подписи (JWKS): по расписанию + принудительно при инциденте.
Dual-key rollout: публикуйте новую ключевую пару заранее (kid2), подпишите токены ей, держите старую (kid1) для валидации до исчерпания TTL.
Refresh-rotation: каждый обмен refresh → новый токен, старый немедленно становится недействительным; повтор — сигнал компрометации.
Revocation: для JWT — списки отозванных `jti` на короткий срок; для reference токенов — немедленная блокировка на AS.
Сценарии break-glass: временные статические креды с минимальными правами и жестким TTL, фиксируйте в журнале.
Rate limiting, bot-защита и защита от перебора
Трехслойные лимиты: per-key / per-IP / per-организация.
Burst + sustained: токен-бак/скользящее окно.
Сложные проверки: device fingerprint, поведенческие сигналы, geo/ASN аномалии, CAPTCHA только для UI.
Lockout/slowdown при переборе подписи/HMAC и неуспешных попытках аутентификации.
Логирование, метрики и SLO
Минимальный набор логов: `request_id`, `client_id`, `sub`, `aud`, `scope`, `decision`, `reason`, `jti`, `ip`, `asn`, `latency`, `quota_state`.
Метрики:- Успешность валидации токенов (%), p95 времени верификации.
- Частота replay-отклонений, дубликатов Idempotency-Key.
- Доля запросов с PoP/DPoP/mTLS.
- Ошибки `aud/scope`, истекшие `exp`, сдвиги времени (NTP).
- Доступность Auth/AS ≥ 99.95%/мес; p95 introspection ≤ 50 мс.
- Ноль токенов с TTL < 60 c в проде (охранная метрика).
- Менее 0.1% ошибок `aud/scope` в день (качество интеграций).
Конфигурационные примеры
Envoy: проверка JWT и audience
yaml http_filters:
- name: envoy. filters. http. jwt_authn typed_config:
providers:
as:
issuer: https://auth. example. com/
audiences: ["wallet-api"]
remote_jwks:
http_uri:
uri: https://auth. example. com/.well-known/jwks. json cluster: jwks_cluster cache_duration: 600s rules:
- match: { prefix: "/v1/withdraw" }
requires:
provider_and_audiences:
provider_name: as audiences: ["wallet-api"]
NGINX: mTLS к backend
nginx proxy_ssl_server_name on;
proxy_ssl_name wallet. internal;
proxy_ssl_certificate /etc/nginx/mtls/client. crt;
proxy_ssl_certificate_key /etc/nginx/mtls/client. key;
proxy_ssl_trusted_certificate /etc/nginx/mtls/ca. crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
Пример заголовка подписи (вебхуки)
X-Signature: t=1730803210,n=ac12...,s=base64(HMAC_SHA256(secret, "POST\n/webhook\nsha256(body)\n1730803210\nac12..."))
Сервер отклоняет, если `t` старше 300 c, `n` уже встречался, либо `s` не бьется.
Защита данных и приватность
Минимизируйте клеймы (особенно PII) и срок жизни.
Шифруйте чувствительные клеймы (JWE) для сторонних интеграций.
Mask/DLP в логах: не логировать тела с PAN/PII, токены — только `kid`/флаги, не сам секрет.
Типичные ошибки
Длинноживущие access-токены и «вечные» refresh.
Отсутствие `aud`/`scope` → токены многоцелевые.
Подпись вебхуков без `timestamp`/`nonce`.
Проверка JWT только в приложении, а не на гейтвее (PEP).
Отсутствие ротаций и dual-key rollout.
CORS «» и разрешенные небезопасные методы без контроля заголовков.
Хранение токенов в `localStorage` без BFF.
Дорожная карта внедрения
1. Инвентаризация API и классификация (публичные/партнерские/внутренние, чувствительность).
2. Выбор модели AuthN: OAuth2/OIDC для пользовательских, mTLS+Client Credentials/HMAC для m2m.
3. Токены: короткие TTL, строгий `aud`, скоупы, DPoP/PoP для критичных операций.
4. PEP на гейтвее: валидация JWT, подписи и rate limits до приложения.
5. Анти-replay и идемпотентность: timestamp/nonce/Idempotency-Key.
6. Ротации и JWKS: dual-key, автоматизация и алертинг.
7. Наблюдаемость: метрики/SLO, журналы доступа, UEBA-сигналы.
8. Учения: отозв ключа подписи, утечка refresh, перегрузка квот.
Специфика для iGaming/финтех
Платежи/выплаты: только mTLS + PoP/HMAC, строгие скоупы (`withdraw.create`), idempotency обязателен.
Партнеры (PSP/провайдеры контента): per-partner ключи/сертификаты, IP/ASN allow-list, отдельные квоты и дашборды.
GDPR/PCI DSS: минимизация клеймов, запрет PII в токенах сторонних, логирование доступа к чувствительным ресурсам, регулярные access review.
Anti-abuse: поведенческие лимиты, гео-контроль, защита от бонус-абьюза на уровне API.
FAQ
JWT или reference token?
JWT — производительность и автономность; reference — централизованный отзыв и простота инцидент-реакции. Часто гибрид: внешним — JWT, внутренним — reference.
Нужен ли JWE?
Только если payload содержит PII/секреты. Иначе — JWS с минимальными клеймами.
Можно ли жить на API-ключах?
Да, но только с коротким TTL, строгими квотами, IP-allow-list и подписью запросов. Для пользователей — предпочтительно OAuth/OIDC.
DPoP/PoP обязательно?
Не всегда. Но для high-risk операций (платежи, выводы) — крайне желателен.
Итог
Надежная безопасность API строится на короткоживущих токенах, точных скоупах и аудитории, защищенных каналах (TLS/mTLS), подписи запросов и строгой анти-replay защите, усиленных лимитами и наблюдаемостью. Добавьте автоматизированные ротации, dual-key rollout и политический контроль на гейтвеях — и ваш API станет устойчивым к утечкам, повторам и злоупотреблениям, сохранив при этом высокую производительность и управляемость.