PKCE

PKCE (Proof Key for Code Exchange, RFC 7636, "pixy") — расширение OAuth 2.0, защищающее Authorization Code Flow от перехвата кода. Обязательный дефолт для public clients (mobile, SPA). В OAuth 2.1 — для всех.

Атака которую PKCE предотвращает

На mobile: приложение регистрирует custom-scheme:// для redirect_uri. Другое (вредоносное) приложение может зарегить тот же scheme и перехватить authorization code.

Раньше был client_secret — но в mobile его хранить негде.

Как работает

  1. Клиент генерит code_verifier — случайные 43-128 символов.
  2. Считает code_challenge = BASE64URL(SHA256(code_verifier)).
  3. В /authorize шлёт code_challenge + code_challenge_method=S256.
  4. AS запоминает.
  5. При обмене кода на токен — клиент шлёт code_verifier.
  6. AS считает SHA256, сверяет с ранее сохранённым challenge. Не совпало — отказ.
code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"

code_challenge = base64url(sha256(code_verifier))
              = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"

method: plain vs S256

PKCE и confidential clients

Раньше считалось "с client_secret PKCE не нужен". Теперь (OAuth 2.1, BCP): нужен всем. Второй слой защиты.

Реализация

# JS
const verifier = crypto.getRandomValues(new Uint8Array(32));
const v_b64 = base64url(verifier);
const challenge = base64url(await crypto.subtle.digest('SHA-256', verifier));
localStorage.setItem('pkce_verifier', v_b64);
window.location = `${authURL}?...&code_challenge=${challenge}&code_challenge_method=S256`;

См. также