Статья по протоколу OAuth 2.0 (OAuth 2.0 Protocol Cheatsheet)

Статья описывает актуальные практики безопасности OAuth 2.0 в духе RFC. OAuth стал стандартом защиты API и основой федеративного входа через OpenID Connect. OpenID Connect 1.0 — простой слой идентичности поверх OAuth 2.0: клиент может проверить личность пользователя по результату аутентификации у сервера авторизации и получить базовый профиль в совместимом, REST-подобном виде.

Примечание. OAuth 2.0 допускает разные типы токенов под разные требования. Bearer-токены (RFC 6750) — простота и широкое распространение. Токены Proof of Possession (PoP) — криптографическая привязка токена к клиенту. Выбор типа зависит от модели угроз, требований к безопасности и ограничений внедрения.

Термины

  • Клиент (Client) — приложение, которое по поручению владельца ресурса запрашивает защищённые ресурсы с его разрешения. «Клиент» не задаёт реализацию (сервер, десктоп, мобильное устройство и т.д.).
  • Сервер авторизации (Authorization Server, AS) — сервер, который после успешной аутентификации владельца ресурса и получения согласия выдаёт клиенту токены доступа.
  • Владелец ресурса (Resource Owner, RO) — субъект, способный разрешить доступ к защищённому ресурсу. Часто это конечный пользователь; возможны организация или система.
  • Сервер ресурсов (Resource Server, RS) — сервер с защищёнными ресурсами, принимающий запросы с токенами доступа.

  • Токены доступа (Access Tokens) — абстракция вместо разных схем авторизации (логин/пароль, assertion и т.д.): один формат, понятный RS. Можно выдавать короткоживущие токены и не заставлять RS понимать множество схем аутентификации. Чаще всего — bearer (RFC 6750): для доступа к API достаточно значения токена. Раз любой, у кого есть bearer, может его использовать, bearer нужно ограничивать одной аудиторией (одним RS), чтобы сузить последствия утечки.

  • Токены обновления (Refresh Tokens) — учётные данные для получения новых access-токенов при истечении или отзыве текущего, либо для токенов с тем же или более узким scope. Их нужно защищать механизмами sender-constraint (DPoP или mTLS) или ротацией refresh-токенов.

  • Токены Proof of Possession (PoP) — access или refresh, криптографически привязанные к клиенту (например DPoP, RFC 9449, или mTLS-bound access tokens, RFC 8705). Клиент владеет закрытым ключом и при использовании токена доказывает владение ключом. Сильнее защита при перехвате токена, выше требования к управлению ключами и генерации proof.

Базовые правила OAuth 2.0

  1. Клиент и AS не должны отдавать URL, которые перенаправляют браузер пользователя на произвольный URI из query-параметра («открытые редиректоры») — иначе возможна эксфильтрация кодов авторизации и токенов.
  2. Если клиент убедился, что AS поддерживает PKCE, можно опираться на защиту от CSRF, которую даёт PKCE. В потоках OpenID Connect параметр nonce даёт защиту от CSRF. Иначе — одноразовые пользовательские CSRF-токены в параметре state, надёжно привязанные к пользовательскому агенту.
  3. Если клиент взаимодействует с несколькими AS, используйте параметр эмитента iss как контрмеру (или значение iss в ответе авторизации, например claim iss в ID Token в OpenID).
  4. Если других контрмер при нескольких AS нет, клиент может использовать разные redirect URI для различения authorization и token endpoint.
  5. AS не пересылает и не редиректит запрос, в котором могли случайно оказаться учётные данные пользователя.

PKCE (Proof Key for Code Exchange)

Публичные клиенты OAuth 2.0 с Authorization Code Grant уязвимы к перехвату кода авторизации. PKCE (часто произносят «пикси») снижает этот риск.

Изначально PKCE ориентировали на нативные приложения, затем механизм стал обычной практикой. Он мешает не только подстановке кода, но и выкупу украденного кода у AS без знания code_verifier.

  1. Клиент предотвращает инъекцию (replay) кода в ответ авторизации через PKCE; допустимы параметр OpenID Connect nonce и соответствующий claim в ID Token. Challenge PKCE или nonce должны быть привязаны к транзакции и безопасно связаны с клиентом и пользовательским агентом, где начата транзакция. Примечание: PKCE защищает коды авторизации; access и refresh защищайте sender-constrained токенами.
  2. С PKCE клиент должен выбирать метод challenge так, чтобы не раскрывать verifier в запросе авторизации; иначе атакующий, читающий запрос, ломает PKCE. AS обязан поддерживать PKCE.
  3. Если клиент передал валидный code_challenge, AS на token endpoint обеспечивает корректное использование code_verifier.
  4. AS снижает риск downgrade PKCE: запрос токена с code_verifier принимается только если в запросе авторизации был code_challenge.

Implicit grant

Implicit grant — упрощённый вариант кода для браузерных клиентов на JavaScript: вместо кода клиент сразу получает access token после авторизации владельца ресурса. Промежуточных учётных данных (кода) нет — отсюда «implicit».

  1. Клиент использует response type code (authorization code) или другой тип, при котором access token выдаётся в ответе token endpoint, а не во фронт-канале (например code id_token). Так AS может обнаруживать replay, уменьшается поверхность атаки (токены не светятся в URL), проще применить sender-constraint (например DPoP).

Защита от повторного использования токена

Безопасность токенов — ключевая часть OAuth 2.0. Sender-constrained токены связывают токен с клиентом. PoP — частный случай: криптографическая привязка к закрытому ключу клиента; при каждом использовании токена клиент доказывает владение ключом — дополнительная аутентификация на уровне использования токена.

Сравнение механизмов PoP

DPoP (Demonstration of Proof of Possession, RFC 9449):

  • Клиент генерирует пару ключей. AS может sender-constrain access token к публичному ключу клиента (например claim cnf с отпечатком JWK jkt) — опционально и зависит от реализации. На каждый запрос к API клиент добавляет proof владения закрытым ключом — обычно JWT, подписанный этим ключом, с хешем access token. RS проверяет и токен, и DPoP-proof (включая хеш токена), чтобы убедиться, что запрос от легитимного держателя токена.
  • mTLS не обязателен; proof в HTTP-заголовках; подходит браузерам и мобильным клиентам; на запрос — дополнительные криптооперации.

Mutual TLS Certificate-Bound Access Tokens (RFC 8705):

  • Клиент аутентифицируется TLS client certificate при рукопожатии (mTLS). AS привязывает access token к отпечатку сертификата через cnf. RS проверяет, что сертификат в TLS-сессии совпадает с привязкой в токене.
  • Работа на транспортном уровне; использует инфраструктуру TLS; PKI или самоподписанные сертификаты; аутентификация при установлении соединения; отдельный proof на каждый запрос не нужен.

Когда использовать PoP-токены

PoP особенно уместен, когда нужны усиленные свойства токена. Рассмотрите PoP, если:

  • access token используется для нескольких аудиторий (RS) — в отличие от bearer, который должен быть ограничен одной аудиторией;
  • API обрабатывает чувствительные данные (финансы, здравоохранение, ПДн и т.д.);
  • высокоценные операции (платежи, критичные действия);
  • долгоживущие токены;
  • кросс-организационный доступ (B2B, несколько доменов безопасности);
  • мобильные и нативные приложения с особыми рисками среды;
  • распределённая архитектура: токены пересекают несколько сетевых границ.

Выбор подхода — по требованиям безопасности, текущей инфраструктуре, возможностям клиента и эксплуатационным ресурсам.

  1. Для усиленной защиты от replay AS и RS могут sender-constrain access token: OAuth 2.0 с mTLS (RFC 8705) или DPoP (RFC 9449) — криптографическая привязка к клиенту через proof владения ключом.
  2. Refresh token — sender-constrained (DPoP или mTLS) или с ротацией (новый refresh, старый сразу инвалидируется для обнаружения replay). Примечание: PoP на refresh + ротация даёт defense in depth.

Ограничение привилегий access token

  1. Привилегии access token должны быть минимальны для сценария. Это ограничивает злоупотребление клиентом сверх разрешения владельца ресурса и пользователя сверх политики безопасности; при утечке токена ущерб меньше. Сочетайте с sender-constrained токенами.
  2. Access token ограничен конкретными RS (audience), желательно одним RS. AS связывает токен с RS; каждый RS на каждом запросе проверяет, что токен предназначен именно для него — иначе отказ. Клиент и AS могут использовать scope и resource для указания целевого RS.
  3. Access token ограничен конкретными ресурсами и действиями на RS. AS связывает токен с ресурсом и действиями; RS проверяет соответствие каждому запросу — иначе отказ. Могут использоваться scope и authorization_details.

Resource Owner Password Credentials Grant

  1. Grant Resource Owner Password Credentials не используется. Он небезопасно передаёт учётные данные владельца ресурса клиенту и расширяет поверхность атаки.

Аутентификация клиента

  1. AS по возможности применяет аутентификацию клиента. Рекомендуются асимметричные методы: mTLS или private_key_jwt (OpenID Connect). При асимметрии AS не хранит чувствительные симметричные ключи клиента — устойчивее к ряду атак.

Прочие рекомендации

  1. AS не даёт клиентам влиять на значение client_id, sub или других claim, которые можно спутать с подлинным владельцем ресурса. Рекомендуется сквозной TLS.
  2. Ответы авторизации не передаются по незашифрованным каналам. AS не должен разрешать redirect URI со схемой http, кроме нативных клиентов с редиректом на loopback.

Ссылки:

© Перевод на русский язык. Оригинальные материалы: OWASP Cheat Sheet Series.
Этот проект использует материалы OWASP, распространяемые по лицензии CC BY-SA 4.0.