Как настроить перенаправление на `refresh-token` endpoint при истечении срока жизни `access token` в проекте `asp.net core web api`, используя конфигурацию аутентификации с `AddJwtBearer`? В данный момент, событие `OnAuthenticationFailed` срабатывает при получении `HttpStatusCode401`, но `context.Response.Redirect()` не выполняет перенаправление.
Для настройки перенаправления на `refresh-token` endpoint при получении ошибки `AuthenticationFailed` в `asp.net core web api`, вы можете использовать следующий подход:
1. Во-первых, вам нужно добавить обработчик события `OnAuthenticationFailed` в методе `ConfigureServices` вашего `Startup` класса:
```c#
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
// Ваш код для перенаправления на refresh-token endpoint
context.Response.Redirect("/api/refresh-token");
}
return Task.CompletedTask;
}
};
});
```
2. Затем вам нужно добавить контроллер для `refresh-token` endpoint, где клиент может обменять `refresh token` на новый `access token`. Например:
```c#
[HttpPost("refresh-token")]
public async Task<IActionResult> RefreshToken()
{
// Ваш код для обмена refresh token на новый access token
return Ok();
}
```
3. Наконец, проверьте, что ваши `access token` и `refresh token` настроены и используются правильно в вашем проекте.
Теперь, при истечении срока действия `access token`, при получении ошибки `AuthenticationFailed` произойдет перенаправление на `refresh-token` endpoint, где клиент сможет получить новый `access token`.
Решил. Как это всё делается? Внутрь onAuthenticationFailed вставляем этот код:
if (context.Exception?.GetType() == typeof(SecurityTokenExpiredException)) { IJwtService jwtService = context.HttpContext.RequestServices.GetService<IJwtService>(); if (context.Request.Cookies.TryGetValue("refresh-token", out string refreshToken)) { Result<ClaimsPrincipal> principalResult = jwtService.ValidateAndDecodeToken(refreshToken); if (!principalResult.IsSuccess || principalResult.Value == null) { return Task.CompletedTask; } Result<string> renewAccessTokenResult = jwtService.Encode(principalResult.Value); if (!renewAccessTokenResult.IsSuccess && renewAccessTokenResult.ValidationErrors.Any()) { return Task.CompletedTask; } context.Response.Cookies.Append("access-token", renewAccessTokenResult.Value); context.Response.StatusCode = 200; context.HttpContext.User = principalResult.Value; context.Principal = principalResult.Value; context.Success(); } } return Task.CompletedTask;
Т.е.. вызывает сервис, берёмrefresh tokenи из него извлекаемClaimPrincipal, далее на его основе делаемaccess tokenиз того же сервиса и обрабатываем запрос, что бы он возвращал нужный статус. Как говорил Andrei SunnyPh , это допустимая практика (Спасибо)
Клиент сам должен следить за временем жизни токена и сам делать рефреш.