Вопрос 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]]