Какой статус код HTTP-запроса возвращается при истекшем сроке годности токена?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ: Статус-код при истекшем токене
При истечении срока годности JWT (JSON Web Token) или любого другого токена аутентификации, общепринятым и рекомендованным статус-кодом HTTP-ответа является 401 Unauthorized, иногда с дополнительным заголовком WWW-Authenticate. Крайне редко может использоваться 403 Forbidden, но это считается антипаттерном для данной ситуации. Разберем детали.
Почему именно 401 Unauthorized?
Согласно спецификации RFC 7235 (и ранее RFC 2616), статус 401 Unauthorized означает, что запрос не был применён, поскольку ему не хватает действительных учётных данных аутентификации для целевого ресурса. Истёкший токен перестаёт быть действительным учётным данным, даже если он был правильно сформирован и подписан. Клиент должен понять, что ему необходимо представить новые, свежие учётные данные.
Код 403 Forbidden указывает, что сервер понял запрос, но отказывается его авторизовать, часто из-за недостатка прав у аутентифицированного пользователя. Проблема с истёкшим токеном — не в правах (authorization), а в недействительности самих учётных данных (authentication).
Типичная реализация в ASP.NET Core
Вот пример middleware или атрибута в C#, который проверяет срок действия токена и возвращает соответствующий ответ:
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
[HttpGet("data")]
[Authorize] // Атрибут, активирующий проверку аутентификации
public IActionResult GetSecureData()
{
// Если токен валиден, выполнится этот код
return Ok(new { message = "Secret data" });
}
}
Глобальная обработка истёкшего токена часто настраивается в конфигурации аутентификации:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true, // Ключевой параметр: проверка срока действия
ValidateIssuerSigningKey = true,
// ... другие параметры
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception is SecurityTokenExpiredException)
{
context.Response.StatusCode = 401;
context.Response.Headers.Add("WWW-Authenticate", "Bearer error=\"invalid_token\", error_description=\"The token has expired\"");
// Можно вернуть кастомный JSON
context.Response.WriteAsync(JsonSerializer.Serialize(new
{
error = "token_expired",
message = "Access token has expired. Please refresh it."
}));
}
return Task.CompletedTask;
}
};
});
Важные аспекты и best practices
- Стандартизация (
WWW-Authenticateзаголовок): Для соблюдения стандарта Bearer Token (RFC 6750) в ответе с кодом 401 стоит возвращать заголовок:WWW-Authenticate: Bearer error="invalid_token", error_description="The access token expired"
Это помогает клиентам (особенно браузерам или стандартным HTTP-клиентам) автоматически понять причину отказа.
-
Структура тела ответа: Хотя тело ответа для 401 не регламентировано, рекомендуется возвращать машиночитаемый JSON для API:
{ "statusCode": 401, "error": "Unauthorized", "message": "Token expired", "timestamp": "2023-10-26T12:00:00Z" } -
Разделение ошибок: В продакшн-системах часто разделяют ошибки внутри
401:
* **Нет токена** -> `401` с описанием `"Missing token"`.
* **Истёкший токен** -> `401` с описанием `"Token expired"` (как в нашем случае).
* **Неверная подпись/формат** -> `401` с описанием `"Invalid token"`.
Это реализуется через обработчик событий, как в коде выше.
- Отличие от процесса Refresh: Сам статус
401сигнализирует об ошибке на текущем запросе. Механизм обновления токена (Refresh Token) — это отдельный бизнес-процесс, инициируемый клиентом на основе полученной ошибки. Обычно клиент (например, SPA или мобильное приложение) перехватывает ответ401с описанием"expired"и автоматически отправляет запрос на специальный эндпоинт (например,POST /api/auth/refresh), используя долгоживущий refresh token для получения новой пары access/refresh токенов, после чего повторяет исходный запрос.
Чего делать не стоит
- Не использовать
403 Forbiddenдля истёкшего токена. Это сбивает с толку клиентскую логику и нарушает семантику HTTP. - Не выбрасывать
500 Internal Server Error— проблема не на стороне сервера, а в присланных клиентом данных (токене). - Не создавать кастомные статус-коды (например,
419или498). Хотя некоторые провайдеры (как, например, Nginx в прошлом предлагал498 Token Expired), это нарушает стандарт и усложняет поддержку клиентами.
Итог: Для истёкшего токена всегда возвращайте HTTP 401 Unauthorized с ясным описанием ошибки в заголовке WWW-Authenticate и/или теле ответа. Это соответствует RFC, однозначно интерпретируется клиентами и является краеугольным камнем при построении надёжных и стандартизированных RESTful или GraphQL API.