Открыть сервисСервис

HTTP 401 Unauthorized

HTTP 401 Unauthorized — код состояния HTTP, указывающий, что запрос не был аутентифицирован: клиент не предоставил учётные данные (или предоставил неверные), необходимые для доступа к запрашиваемому ресурсу. Код 401 входит в категорию клиентских ошибок (4xx) и означает, что сервер понял запрос, но отказывается его выполнять до тех пор, пока клиент не представит подтверждённой личности. Стандарт определён в документе RFC 9110 (ранее — RFC 7231), который описывает семантику HTTP-методов и кодов состояния.

Семантика и отличие от 403

Ключевое отличие 401 от близкого кода 403 Forbidden заключается в том, что 401 подразумевает: аутентификация возможна и может привести к успеху, если клиент повторит запрос с корректными учётными данными. Код 403 означает, что сервер понял личность запросившего, но доступ всё равно запрещён — повторная аутентификация ситуацию не изменит.

Согласно спецификации, ответ 401 обязан содержать заголовок WWW-Authenticate с указанием схемы аутентификации (Basic, Bearer, Digest и др.), которую сервер ожидает от клиента. На практике многие веб-серверы и API-платформы отдают 401 и без этого заголовка, что формально нарушает RFC, но широко распространено.

Типичные причины возникновения

  • Отсутствие заголовка Authorization в запросе к защищённому ресурсу.
  • Истёкший срок действия токена доступа (например, JWT).
  • Неверный логин или пароль при Basic-аутентификации.
  • Некорректный формат токена (отсутствует схема Bearer, опечатка в значении).
  • Отсутствие cookie сессии или её истечение.

Формат ответа

Пример типичного ответа сервера:

``` HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example" Content-Type: application/json

{"error": "unauthorized", "message": "Token expired"} ```

Тело ответа не нормализовано стандартом: сервер может вернуть HTML-страницу, JSON-объект или пустое тело. Многие фреймворки (Spring Security, Django REST Framework, Express с Passport.js) формируют собственный формат ошибки.

Обработка на клиенте

Браузеры при получении 401 с заголовком WWW-Authenticate: Basic показывают системное окно ввода логина и пароля. Для схем Bearer и Digest поведение зависит от браузера и контекста.

При работе с API стандартный паттерн — перехватить 401 и попытаться обновить токен через refresh-токен, после чего повторить исходный запрос. Если обновление невозможно, клиент считается неаутентифицированным и перенаправляется на страницу входа.

Отличие от смежных кодов

КодНазваниеЗначение
401UnauthorizedНет аутентификации; повтор с учётными данными имеет смысл
403ForbiddenАутентификация не поможет; доступ запрещён
407Proxy Authentication RequiredТребуется аутентификация перед прокси-сервером
440Login Timeout (IIS)Сессия входа истекла (нет в стандарте, используется Microsoft IIS)
498Invalid Token (устаревший)Некорректный токен; использовался некоторыми API, в RFC не входит

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

Ответ 401 не должен раскрывать, существует ли запрашиваемый ресурс или какая именно часть учётных данных неверна — иначе возможна атака перебором (brute force) с разведкой валидных логинов. Рекомендовано использовать единообразные сообщения вида «неверные учётные данные».

Частая ошибка разработчиков — возвращать 200 OK с JSON вида {"error": "unauthorized"} вместо 401. Это ломает стандартную обработку в HTTP-клиентах, прокси и браузерах.

401 в российских реалиях

В российской веб-разработке код 401 широко используется в государственных информационных системах, интегрированных с ЕСИА (Единой системой идентификации и аутентификации). При обращении к порталу Госуслуг и связанным с ним сервисам пользователь проходит аутентификацию через ЕСИА, после чего клиентское приложение получает токен доступа; истечение токена приводит к ответу 401 и необходимости повторного входа. Стандарты взаимодействия с ЕСИА описаны в открытых документации регулятора и используют OAuth 2.0 с грантами, адаптированными под российские требования к аутентификации.

Историческая справка

Код 401 появился в первой версии спецификации HTTP (HTTP/0.9 не имел кодов состояния, HTTP/1.0, 1996) и был описан в RFC 1945, затем в RFC 2616 (1999) и пересмотрен в RFC 7235 (2014). В актуальной редакции RFC 9110 (2022) семантика кода сохранена без существенных изменений.

Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru