awesome-everything EN
↑ Обратно к восхождению

Безопасность

Authorization code flow с PKCE

Суть Как обязательный PKCE в OAuth 2.1 предотвращает перехват кода, почему exact-match redirect URI блокирует open-redirect exfiltration, и от чего защищают state и nonce.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 10 min

Атакующий мониторит исходящие запросы мобильного приложения и перехватывает one-time authorization code из redirect URL. Без PKCE он обменивает код на токены и захватывает аккаунт. PKCE — это замок, делающий украденный код бесполезным.

Как работает PKCE — шаг за шагом

PKCE (Proof Key for Code Exchange, RFC 7636) добавляет криптографический challenge к authorization code flow. OAuth 2.1 мандатит его для каждого клиента, включая confidential server-side приложения.

Перед редиректом:

  1. Клиент генерирует code_verifier — случайную URL-safe строку 43–128 символов (криптографически случайную).
  2. Клиент вычисляет code_challenge = base64url(SHA-256(code_verifier)).
  3. Клиент отправляет code_challenge (но НЕ code_verifier) в authorization server в /authorize запросе.

После согласия пользователя: 4. Authorization server возвращает one-time code в редиректе. Сохраняет code_challenge рядом с кодом.

Обмен на токены: 5. Клиент POST-ит на /token с code И оригинальным code_verifier. 6. Authorization server хеширует code_verifier, сравнивает с сохранённым code_challenge. Совпадение → токены выданы. Несовпадение → запрос отклонён.

Атакующий, перехвативший код на шаге 4, не может его обменять — ему нужен code_verifier, который никогда не передавался по сети.

Привязка кода через PKCE
1Клиент генерирует code_verifier (случайный 43–128 chars, остаётся локально)
2Клиент вычисляет code_challenge = base64url(SHA-256(verifier))
3/authorize несёт только code_challenge (хеш, verifier остаётся секретом)
4Auth server сохраняет challenge → выдаёт code в redirect URL
5/token несёт code + code_verifier — auth server хеширует, сравнивает, выдаёт токены
Атакующий получает code на шаге 4, но не verifier → вызов /token отклонён.

Правило exact-match redirect URI

OAuth 2.1 требует, чтобы redirect_uri в token request точно совпадал с pre-registered URI — никаких wildcard, префиксов пути, partial match.

Без этого правила: атакующий может триггернуть flow с redirect_uri=https://yourapp.com/comments?next=https://attacker.com. Если у твоего приложения есть open-redirect на /comments, authorization code оказывается на сервере атакующего. Exact-match закрывает это: URI должен совпадать character-for-character с зарегистрированным значением.

Для native apps, где нельзя надёжно зарегистрировать URL (deep links, custom URI schemes), OAuth 2.1 + RFC 8252 требуют http://127.0.0.1:RANDOM_PORT (loopback) или private-use URI scheme, зарегистрированный с OS.

State и nonce: два отдельных anti-attack токена

State — anti-CSRF OAuth: клиент генерирует случайное значение на /authorize, сервер эхо-нит его в редиректе, клиент проверяет совпадение. Без state атакующий может отправить жертве crafted /authorize URL, указывающий на redirect атакующего — при клике браузер жертвы тихо завершает flow под аккаунтом атакующего.

Nonce — anti-replay OIDC: клиент отправляет случайное значение в /authorize; IdP embed-ит его внутрь id_token. Клиент проверяет, что nonce в токене совпадает с отправленным. Без nonce атакующий, захвативший id_token из другого канала, может replay-нуть его в другую сессию.

Оба per-request случайные. Оба валидируются server-side. Ни один не optional в современных flow.

Викторина

Зачем OAuth 2.1 требует PKCE для ВСЕХ клиентов, включая confidential server-side?

Викторина

Клиент валидирует подпись id_token и iss, но скипает проверку nonce. Какая атака становится возможной?

Расставь шаги по порядку

Поставь full authorization code + PKCE flow в порядке:

  1. 1 Клиент генерирует code_verifier и code_challenge (SHA-256 от verifier)
  2. 2 Клиент редиректит браузер на /authorize с code_challenge, state, nonce, client_id, redirect_uri
  3. 3 Пользователь аутентифицируется на authorization server и одобряет scope
  4. 4 Authorization server редиректит на redirect_uri с code и state
  5. 5 Клиент верифицирует state совпадает; POST-ит на /token с code + code_verifier
  6. 6 Authorization server хеширует verifier, сравнивает с stored challenge, выдаёт access + ID-токены
  7. 7 Клиент валидирует ID-токен (подпись, iss, aud, exp, nonce) и читает identity пользователя
Вспомните перед уходом
  1. 01
    Что предотвращает PKCE и как?
  2. 02
    Почему OAuth 2.1 требует exact-match redirect URI?
  3. 03
    В чём разница между параметром state и параметром nonce?
Итог

Authorization code flow с PKCE — единственный grant type, разрешённый для user-facing приложений в OAuth 2.1. PKCE предотвращает перехват кода: verifier никогда не покидает клиента, поэтому украденный код не может быть обменян. Exact-match redirect URI предотвращает open-redirect code exfiltration. Параметры state и nonce закрывают два независимых attack window — CSRF на flow и replay на ID-токене. Все три обязательны в OAuth 2.1; пропуск любого — документированный CVE вектор.

Связанные уроки
встречается в202
Продолжить восхождение ↑Валидация ID-токена и управление JWKS-кешем
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.