Proof Key for Code Exchange (PKCE)
Proof Key for Code Exchange (Ключ подтверждения для обмена кодами, PKCE) — это дополнительная защита для протокола OAuth 2.0, которая предотвращает перехват авторизационных кодов. PKCE особенно важен для мобильных приложений и одностраничных веб-приложений, где невозможно безопасно хранить секретные ключи.
Механизм PKCE был разработан в 2015 году и описан в стандарте RFC 7636
OAuth 2.0 и проблема безопасности
Чтобы понять назначение PKCE, рассмотрим принцип работы протокола OAuth 2.0 и его уязвимости.
С помощью OAuth 2.0 пользователь может разрешить приложению получить доступ к его данным в другом сервисе без передачи пароля. Например, вы можете дать приложению для планирования встреч право читать ваш Яндекс Календарь, не сообщая ему свой пароль от сервиса.
Для этого приложению нужно получить от сервера авторизации (например, Яндекс ID) временный авторизационный код, а затем обменять его на access-токен. При обычном обмене приложение подтверждает свою подлинность с помощью client secret — секретного ключа, известного только ему и серверу авторизации. Однако это работает только для серверных клиентов, которые способны надежно хранить секреты. Публичные клиенты лишены такой возможности:
- Мобильные приложения — секрет можно извлечь через декомпиляцию.
- Одностраничные приложения — весь JavaScript-код виден в браузере.
В таких случаях использование client secret невозможно. Без дополнительной защиты злоумышленник может перехватить авторизационный код и обменять его на access-токен. Именно эту проблему и решает PKCE.
Принцип работы PKCE
PKCE дополняет процесс авторизации следующим образом:
-
Приложение генерирует code verifier (верификатор кода) — криптографически случайную строку длиной от 43 до 128 символов. Эта строка уникальна для каждого запроса авторизации и не покидает приложение до момента обмена на токен.
-
На основе code verifier приложение генерирует code challenge (вызов кода). Существует два метода генерации:
-
Приложение перенаправляет пользователя на сервер авторизации, добавляя в запрос code challenge и метод его создания.
Пример URL запроса
https://oauth.yandex.ru/authorize? response_type=code& client_id=0a1b2c3d4e5f6a7b8c9********& redirect_uri=https://example.com/auth/callback& code_challenge=E9Melhoa2OwvFrEMTJguCHa********& code_challenge_method=S256 -
Сервер авторизации сохраняет code challenge и связывает его с выданным кодом авторизации.
-
После успешной авторизации пользователя сервер перенаправляет его обратно в приложение вместе с кодом авторизации.
-
Приложение отправляет прямой HTTPS-запрос обмена кода на токен, добавляя в него исходный code verifier. Верификатор не может быть перехвачен, так как не попадает в браузер и не передается в URL.
-
Сервер авторизации выполняет проверку: применяет к полученному code verifier указанный метод и сравнивает результат с сохраненным code challenge. Если значения совпадают, сервер выдает access-токен. Если нет — запрос отклоняется.
При таком подходе, даже если злоумышленник перехватит код авторизации, он не сможет обменять его на токен, потому что не знает code verifier, который хранится только в памяти процесса приложения.
Преимущества
Преимущества использования механизма:
- Безопасность для публичных клиентов. PKCE позволяет мобильным и одностраничным приложениям безопасно использовать OAuth 2.0 без необходимости хранить секретные ключи.
- Простота внедрения. Механизм не требует сложной инфраструктуры — достаточно добавить генерацию случайной строки и вычисление хеша.
- Стандартизированность. PKCE описан в RFC 7636 и поддерживается всеми современными провайдерами OAuth 2.0, включая Google, Microsoft, Яндекс и другие.
- Обратная совместимость. Серверы авторизации, поддерживающие PKCE, обычно позволяют использовать его опционально, что не нарушает работу существующих приложений.
- Защита от различных атак. PKCE защищает не только от перехвата кода, но и от атак с подменой приложения.
Ограничения
Несмотря на свою простоту и эффективность, PKCE имеет ряд ограничений и уязвимостей:
- Не заменяет другие меры безопасности. PKCE гарантирует, что токен получит тот, кто его запрашивал, но не легитимизирует самого клиента. Необходимо использовать HTTPS, правильно валидировать URL обратного вызова и применять другие меры безопасности.
- Допускает использование небезопасного метода plain. Серверы должны отклонять такие запросы, если это возможно.
- Требует корректной реализации. Если code verifier генерируется предсказуемым образом, защита становится бесполезной. Важно использовать криптографически стойкий генератор случайных чисел.
- Добавляет сложность. Хотя механизм PKCE относительно прост, он все же добавляет дополнительные шаги в поток авторизации, чем может усложнить отладку и поддержку, а также повысить расходы.
Распространенность и поддержка
PKCE широко поддерживается и рекомендуется современными провайдерами авторизации, а для публичных клиентов может быть даже обязательной частью процесса авторизации.
Большинство современных библиотек и SDK для работы с OAuth 2.0 также автоматически используют PKCE, если сервер его поддерживает. Например:
- AppAuth (iOS, Android) — автоматически применяет PKCE.
- MSAL (Microsoft Authentication Library) — использует PKCE по умолчанию.
- oidc-client-js (JavaScript) — поддерживает PKCE для одностраничных приложений.
Рекомендации по использованию
Хотя PKCE разрабатывался для публичных клиентов, его использование в серверных приложениях при правильной реализации добавляет дополнительный уровень защиты. При внедрении механизма учитывайте следующие рекомендации:
- Используйте только метод S256. Метод plain существует только для поддержки совместимости, в RFC не рекомендуется использовать его без нужды.
- Генерируйте криптографически стойкий code verifier. Используйте встроенные криптографические библиотеки вашего языка программирования.
- Храните code verifier безопасно. В мобильных приложениях используйте защищенное хранилище, в веб-приложениях — память браузера, а не локальную.
- Не используйте один code verifier повторно. Code verifier должен быть уникальным и генерироваться для каждого запроса авторизации.
- Используйте дополнительные меры защиты. PKCE не гарантирует полную защиту, в дополнение к нему требуется как минимум надежная проверка подлинности клиента.
Полезные ссылки
- Технология единого входа (SSO)
- JSON Web Token (JWT)
- Зачем нужны SSL-сертификаты
- RFC 7636: Proof Key for Code Exchange
OAuth 2.0