OAuth 2.0 та OIDC: безпека сучасної автентифікації
OAuth забезпечує роботу «Увійти через Google» по всьому вебу — і часто налаштовується неправильно. Дізнайтеся, як це працює, про поширені вразливості та безпечну реалізацію.
Зміст
- OAuth 2.0 простими словами
- Потік коду авторизації
- PKCE: захист публічних клієнтів
- OpenID Connect (OIDC): додавання автентифікації
- Поширені вразливості та атаки
- Відкрите перенаправлення через redirect_uri
- CSRF параметра state
- Витік токена через Referer
- Атаки плутанини JWT
- Недостатня перевірка обсягу
- Контрольний список безпечної реалізації
OAuth 2.0 простими словами
OAuth 2.0 — це фреймворк авторизації, а не протокол автентифікації. Ця різниця надзвичайно важлива: OAuth відповідає на питання «що цьому застосунку дозволено робити?» — а не «хто цей користувач?» Його ключовий варіант використання — делегований доступ: дозволити стороннєму застосунку читати Ваші файли на Google Drive, не показуючи йому Ваш пароль Google.
Основні учасники OAuth:
- Власник ресурсу: користувач, якому належать дані
- Клієнт: сторонній застосунок, що запитує доступ
- Сервер авторизації: видає токени після отримання згоди користувача (наприклад, сервер авторизації Google)
- Сервер ресурсів: API, що зберігає дані користувача (наприклад, Google Drive API)
Сервер авторизації видає токен доступу, який клієнт використовує для виклику сервера ресурсів від імені користувача. Токени зазвичай є короткоживучими JWT або непрозорими рядками.
Потік коду авторизації
Для серверних веб-застосунків потік коду авторизації є рекомендованим підходом:
- Клієнт перенаправляє користувача на сервер авторизації з параметрами
response_type=code,client_id,redirect_uri,scopeта випадковим параметромstate - Користувач проходить автентифікацію та надає згоду
- Сервер авторизації перенаправляє назад на
redirect_uriклієнта з короткоживучимcodeта значеннямstate - Клієнт перевіряє, що
stateзбігається з відправленим (захист від CSRF), потім обмінюєcodeна токени через POST-запит у зворотньому каналі за допомогою свогоclient_secret - Сервер авторизації повертає
access_tokenта опційноrefresh_tokenтаid_token
Обмін у зворотньому каналі (крок 4) забезпечує безпеку цього потоку — токен доступу ніколи не відображається в URL або історії браузера.
PKCE: захист публічних клієнтів
Мобільні застосунки та SPA (односторінкові застосунки) не можуть безпечно зберігати client_secret — він буде видимий у бінарному файлі застосунку або вихідному коді JavaScript. PKCE (Proof Key for Code Exchange, вимовляється «піксі») вирішує цю проблему:
- Клієнт генерує випадковий
code_verifierта обчислюєcode_challenge = BASE64URL(SHA256(code_verifier)) code_challengeнадсилається в запиті авторизаціїcode_verifierнадсилається в обміні токенів- Сервер авторизації перевіряє відповідність — лише оригінальний клієнт може завершити обмін
PKCE слід використовувати для всіх клієнтів OAuth у 2026 році, включаючи конфіденційних клієнтів. Це забезпечує захист навіть у разі перехоплення коду авторизації.
OpenID Connect (OIDC): додавання автентифікації
OIDC — це тонкий ідентифікаційний шар, побудований поверх OAuth 2.0. Він додає ID-токен — JWT, підписаний сервером авторизації, що містить твердження про автентифікованого користувача (sub, email, name тощо). OIDC — це те, що робить «Увійти через Google» справжньою автентифікацією користувачів, а не просто авторизацією доступу до їхніх даних.
Ключові концепції OIDC:
- ID-токен: JWT для клієнта, щоб перевірити хто є користувачем — ніколи не надсилайте в API
- Токен доступу: для виклику API сервера ресурсів — клієнт повинен ставитися до нього як до непрозорого
- Кінцева точка UserInfo: кінцева точка API, що повертає твердження про користувача при виклику з токеном доступу
nonce: випадкове значення, включене в запит авторизації та перевірене в ID-токені для запобігання атакам відтворення
Поширені вразливості та атаки
Відкрите перенаправлення через redirect_uri
Якщо сервер авторизації не перевіряє суворо redirect_uri, зловмисник може змінити його, щоб він вказував на власний сервер, викрадаючи код авторизації, коли жертва авторизується. Захист: реєструйте точні URI перенаправлення; забороніть підстановочні знаки або зіставлення за шаблоном.
CSRF параметра state
Пропуск або невалідація параметра state дозволяє зловмиснику обманом змусити браузер жертви завершити потік авторизації, ініційований зловмисником, потенційно пов'язуючи обліковий запис жертви з ідентичністю зловмисника. Захист: завжди генеруйте криптографічно випадковий state та перевіряйте його при поверненні.
Витік токена через Referer
Неявний потік (тепер застарілий) повертав токени безпосередньо у фрагменті URL, що могло призвести до витоку через заголовки Referer або історію браузера. Захист: ніколи не використовуйте неявний потік — натомість використовуйте код авторизації + PKCE.
Атаки плутанини JWT
JWT є самодостатніми та потребують ретельної перевірки. Поширені помилки:
- Прийняття
alg: none— вимкніть узгодження алгоритму, завжди явно вказуйте дозволені алгоритми - Використання публічного ключа RS256 як секрету HS256 — жорстко прив'язуйте очікуваний алгоритм на стороні сервера
- Невалідація тверджень
iss,audтаexp
Недостатня перевірка обсягу
Токени доступу повинні мати обсяг, обмежений мінімально необхідними дозволами. API повинні перевіряти, що наданий токен має необхідний обсяг для кожної операції — не припускайте, що дійсний токен означає повний доступ.
Контрольний список безпечної реалізації
- Використовуйте код авторизації + PKCE для всіх клієнтів
- Реєструйте точні URI перенаправлення лише з HTTPS
- Завжди перевіряйте параметр
state(або використовуйте PKCE, який забезпечує еквівалентний захист) - Перевіряйте всі твердження JWT:
iss,aud,exp,nbf, алгоритм - Зберігайте токени в пам'яті (не в localStorage) у SPA — використовуйте
HttpOnlyкуки для токенів оновлення у веб-застосунках - Реалізуйте ротацію токенів: видавайте новий токен оновлення при кожному використанні та анулюйте старий
- Використовуйте короткоживучі токени доступу (5–15 хвилин) з токенами оновлення для підтримки сесії
- Регулярно перевіряйте всі OAuth-застосунки, що мають доступ до Вашого сервера авторизації
- Ніколи не реєструйте та не відображайте токени доступу в URL, журналах або повідомленнях про помилки