Питання 10 · Розділ 6

В чому різниця між 401 та 403?

Різниця між 401 Unauthorized і 403 Forbidden — це різниця між "хто ви?" і "що вам дозволено?".

Мовні версії: English Russian Ukrainian

Junior Level

Різниця між 401 Unauthorized і 403 Forbidden — це різниця між “хто ви?” і “що вам дозволено?”.

401 Unauthorized — “Я вас не знаю”

  • Сервер не знає користувача
  • Потрібно увійти в систему (залогінитися)
  • Приклад: Ви прийшли на роботу без перепустки
GET /profile
→ 401 Unauthorized
→ Фронтенд перенаправляє на сторінку логіна

403 Forbidden — “Я вас знаю, але вам не можна”

  • Сервер знає користувача, але забороняє дію
  • Повторний логін не допоможе — проблема в правах доступу
  • Приклад: У вас є перепустка в офіс, але не в серверну
GET /admin
→ 403 Forbidden
→ Фронтенд показує "Доступ заборонено"

Проста аналогія:

  • 401: Охоронець питає: “Хто ви?” (потрібно пред’явити посвідчення)
  • 403: Охоронець каже: “Я вас знаю, Іванов, але вам не можна в цей кабінет”

Middle Level

401 Unauthorized (Identity Unknown)

  • Суть: Сервер не знає користувача
  • RFC 9110 Requirement: RFC 9110 вимагає, щоб відповідь 401 містила заголовок WWW-Authenticate (наприклад, WWW-Authenticate: Bearer realm="api"). Однак у production API Gateway може його видаляти — це нормально для token-based аутентифікації.
  • Дія: Типова поведінка фронтенду — оновити токен через Refresh Token Flow або перенаправити на сторінку логіна.

403 Forbidden (Identity Known)

  • Суть: Сервер знає користувача, але забороняє дію
  • Дія: Повторний логін не допоможе. Це проблема прав доступу (Scopes, Roles, ACL).
    • Scopes — дозволи на рівні API (наприклад, read:users).
    • Roles — ролі користувача (ADMIN, USER).
    • ACL (Access Control List) — таблиця відповідності користувачів і ресурсів.

Реалізація в Spring Security 6.x

У Spring Security ці дві помилки обробляються різними компонентами:

  1. AuthenticationEntryPoint: Спрацьовує, коли анонімний користувач намагається зайти на захищений ендпоінт (генерує 401)
  2. AccessDeniedHandler: Спрацьовує, коли користувач залогінений, але його GrantedAuthority недостатньо (генерує 403)

Прикордонні випадки

  • Expired Token: Якщо JWT прострочений — повернути 401, а не 403. Мобільні додатки використовують 401 як тригер для оновлення сесії
  • IP Blocking / Rate Limiting: 403 може використовуватися для блокування за IP (WAF). Користувач аутентифікований, але інфраструктура забороняє доступ
  • CSRF: У Spring Security відсутність або невалідність CSRF-токена призводить до 403 Forbidden, навіть якщо користувач — супер-адмін

Діагностика

  • Сплеск 401 може означати проблеми з Identity Provider (Keycloak, Auth0) або Brute-force атаку
  • Постійні 403 від легітимних користувачів — ознака багу в інтерфейсі або маппінгу ролей

Senior Level

Коли НЕ використовувати 401/403

  • Не повертайте 401 для публічних ресурсів — це збиває з пантелику
  • Не використовуйте 403 для rate limiting — для цього є 429 Too Many Requests
  • Для неіснуючих ресурсів краще 404, ніж 403 (щоб не розкривати існування)

Security by Obscurity (Приховування через 404)

Іноді, якщо користувач намагається отримати доступ до секретного ресурсу (наприклад, /admin/top-secret), сервер може повернути 404 Not Found замість 403 Forbidden.

Навіщо? Щоб зловмисник не знав, чи існує ресурс взагалі. Відповідь 403 підтверджує існування ресурсу (“він тут є, але я тобі не дам”).

OAuth2 Scopes vs Roles

У сучасних системах 403 часто виникає через нестачу Scopes у JWT токені:

  • У вас є роль USER (авторизація пройдена)
  • Але токен не має scope write (доступ до POST методу заборонено)

Компоненти Spring Security (деталі)

AuthenticationEntryPoint

Обробляє ситуації, коли неаутентифікований користувач намагається отримати доступ до захищеного ресурсу. Має ініціювати процес аутентифікації.

AccessDeniedHandler

Обробляє ситуації, коли аутентифікований користувач не має необхідних прав. Може логувати спроби несанкціонованого доступу.

Діагностика і Моніторинг

  • Metric: auth_failures_total: Сплеск 401 — проблеми з Identity Provider або Brute-force атака
  • Monitoring 403s: Постійні 403 від легітимних користувачів — баг в інтерфейсі (кнопки без прав) або в маппінгу ролей
  • Audit Logging: Усі відповіді 403 мають логоватися із зазначенням ID користувача і потрібного права для відділу безпеки

🎯 Шпаргалка для співбесіди

Обов’язково знати:

  • 401 Unauthorized = «не знаю хто ви» — потрібна аутентифікація, типова дія — редирект на логін
  • 403 Forbidden = «знаю, але не можна» — проблема в правах доступу (roles, scopes, ACL)
  • 401 за RFC 9110 має містити заголовок WWW-Authenticate
  • У Spring Security: AuthenticationEntryPoint → 401, AccessDeniedHandler → 403
  • Expired JWT = 401 (не 403), мобільні додатки використовують 401 для оновлення сесії
  • Security by Obscurity: іноді повертають 404 замість 403, щоб не підтверджувати існування ресурсу
  • Rate limiting = 429, не 403; помилка CSRF = 403 навіть для супер-адміна

Часті уточнюючі запитання:

  • Що робити фронтенду при 401? — Оновити токен через Refresh Token або перенаправити на логін
  • Що робити фронтенду при 403? — Показати «доступ заборонено», повторний логін не допоможе
  • Коли краще повернути 404 замість 403? — Для секретних ресурсів, щоб не підтверджувати їх існування
  • Чим Scopes відрізняються від Roles? — Scopes — дозволи на рівні API (read:users), Roles — ролі користувача (ADMIN, USER)

Червоні прапорці (НЕ говорити):

  • «401 і 403 — одне й те саме» — 401 = не аутентифікований, 403 = аутентифікований, але немає прав
  • «Для rate limiting потрібен 403» — для цього є 429 Too Many Requests
  • «Повторний логін вирішить проблему 403» — 403 = проблема в правах, не в аутентифікації
  • «Expired Token = 403» — прострочений токен = 401, клієнт повинен оновити сесію

Пов’язані теми:

  • [[Які HTTP статус коди ви знаєте]]
  • [[Що означає Stateless в контексті REST]]
  • [[Що таке REST]]
  • [[Що таке RESTful API дизайн]]
  • [[Як правильно іменувати REST endpoints]]