Статья по протоколу 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
- Клиент и AS не должны отдавать URL, которые перенаправляют браузер пользователя на произвольный URI из query-параметра («открытые редиректоры») — иначе возможна эксфильтрация кодов авторизации и токенов.
- Если клиент убедился, что AS поддерживает PKCE, можно опираться на защиту от CSRF, которую даёт PKCE. В потоках OpenID Connect параметр
nonceдаёт защиту от CSRF. Иначе — одноразовые пользовательские CSRF-токены в параметреstate, надёжно привязанные к пользовательскому агенту. - Если клиент взаимодействует с несколькими AS, используйте параметр эмитента
issкак контрмеру (или значениеissв ответе авторизации, например claimissв ID Token в OpenID). - Если других контрмер при нескольких AS нет, клиент может использовать разные redirect URI для различения authorization и token endpoint.
- AS не пересылает и не редиректит запрос, в котором могли случайно оказаться учётные данные пользователя.
PKCE (Proof Key for Code Exchange)
Публичные клиенты OAuth 2.0 с Authorization Code Grant уязвимы к перехвату кода авторизации. PKCE (часто произносят «пикси») снижает этот риск.
Изначально PKCE ориентировали на нативные приложения, затем механизм стал обычной практикой. Он мешает не только подстановке кода, но и выкупу украденного кода у AS без знания code_verifier.
- Клиент предотвращает инъекцию (replay) кода в ответ авторизации через PKCE; допустимы параметр OpenID Connect
nonceи соответствующий claim в ID Token. Challenge PKCE илиnonceдолжны быть привязаны к транзакции и безопасно связаны с клиентом и пользовательским агентом, где начата транзакция. Примечание: PKCE защищает коды авторизации; access и refresh защищайте sender-constrained токенами. - С PKCE клиент должен выбирать метод challenge так, чтобы не раскрывать verifier в запросе авторизации; иначе атакующий, читающий запрос, ломает PKCE. AS обязан поддерживать PKCE.
- Если клиент передал валидный
code_challenge, AS на token endpoint обеспечивает корректное использованиеcode_verifier. - AS снижает риск downgrade PKCE: запрос токена с
code_verifierпринимается только если в запросе авторизации былcode_challenge.
Implicit grant
Implicit grant — упрощённый вариант кода для браузерных клиентов на JavaScript: вместо кода клиент сразу получает access token после авторизации владельца ресурса. Промежуточных учётных данных (кода) нет — отсюда «implicit».
- Клиент использует 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с отпечатком JWKjkt) — опционально и зависит от реализации. На каждый запрос к 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, несколько доменов безопасности);
- мобильные и нативные приложения с особыми рисками среды;
- распределённая архитектура: токены пересекают несколько сетевых границ.
Выбор подхода — по требованиям безопасности, текущей инфраструктуре, возможностям клиента и эксплуатационным ресурсам.
- Для усиленной защиты от replay AS и RS могут sender-constrain access token: OAuth 2.0 с mTLS (RFC 8705) или DPoP (RFC 9449) — криптографическая привязка к клиенту через proof владения ключом.
- Refresh token — sender-constrained (DPoP или mTLS) или с ротацией (новый refresh, старый сразу инвалидируется для обнаружения replay). Примечание: PoP на refresh + ротация даёт defense in depth.
Ограничение привилегий access token
- Привилегии access token должны быть минимальны для сценария. Это ограничивает злоупотребление клиентом сверх разрешения владельца ресурса и пользователя сверх политики безопасности; при утечке токена ущерб меньше. Сочетайте с sender-constrained токенами.
- Access token ограничен конкретными RS (audience), желательно одним RS. AS связывает токен с RS; каждый RS на каждом запросе проверяет, что токен предназначен именно для него — иначе отказ. Клиент и AS могут использовать
scopeиresourceдля указания целевого RS. - Access token ограничен конкретными ресурсами и действиями на RS. AS связывает токен с ресурсом и действиями; RS проверяет соответствие каждому запросу — иначе отказ. Могут использоваться
scopeиauthorization_details.
Resource Owner Password Credentials Grant
- Grant Resource Owner Password Credentials не используется. Он небезопасно передаёт учётные данные владельца ресурса клиенту и расширяет поверхность атаки.
Аутентификация клиента
- AS по возможности применяет аутентификацию клиента. Рекомендуются асимметричные методы: mTLS или
private_key_jwt(OpenID Connect). При асимметрии AS не хранит чувствительные симметричные ключи клиента — устойчивее к ряду атак.
Прочие рекомендации
- AS не даёт клиентам влиять на значение
client_id,subили других claim, которые можно спутать с подлинным владельцем ресурса. Рекомендуется сквозной TLS. - Ответы авторизации не передаются по незашифрованным каналам. AS не должен разрешать redirect URI со схемой
http, кроме нативных клиентов с редиректом на loopback.
Ссылки:
- RFC 6749: OAuth 2.0 Authorization Framework
- RFC 6750: OAuth 2.0 Bearer Token Usage
- RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
- RFC 9207: OAuth 2.0 Security Best Current Practice
- RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP)
- Mix-Up Attacks (RFC 9207, раздел 4.4)
- Контрмеры против mix-up (RFC 9207, раздел 4.4.2)
© Перевод на русский язык. Оригинальные материалы: OWASP Cheat Sheet Series.
Этот проект использует материалы OWASP, распространяемые по лицензии CC BY-SA 4.0.