Истечение срока действия токена OAuth в приложении MVC6
Итак, у меня есть приложение MVC6, которое включает в себя сервер идентификации (использующий IdentityServer3 ThinkTecture) и приложение веб-служб MVC6.
В приложении веб-сервисов я использую этот код при запуске:
app.UseOAuthBearerAuthentication(options =>
{
options.Authority = "http://localhost:6418/identity";
options.AutomaticAuthentication = true;
options.Audience = "http://localhost:6418/identity/resources";
});
Тогда у меня есть контроллер с действием, которое имеет Authorize
приписывать.
У меня есть приложение JavaScript, которое проходит проверку подлинности на сервере идентификации, а затем использует предоставленный токен JWT для доступа к действию веб-служб.
Это работает, и я могу получить доступ к действию только с действительным токеном.
Проблема возникает, когда истек JWT. Я получаю подробную страницу ошибки ASP.NET 500, которая возвращает информацию об исключении для следующего исключения:
System.IdentityModel.Tokens.SecurityTokenExpiredException IDX10223: проверка продолжительности жизни не выполнена. Срок действия токена истек.
Я довольно плохо знаком с OAuth и безопасностью веб-API в целом, поэтому я могу быть не в своей тарелке, но ошибка 500 не подходит мне для маркера с истекшим сроком действия. Это определенно не дружелюбно для клиента веб-службы.
Это ожидаемое поведение, и если нет, то что мне нужно сделать, чтобы получить более адекватный ответ?
1 ответ
Изменить: эта ошибка была исправлена в ASP.NET Core RC2, и обходной путь, описанный в этом ответе, больше не нужен.
Примечание: этот обходной путь не будет работать на ASP.NET 5 RC1 из-за этой другой ошибки. Вы можете либо перейти на ночные сборки RC2, либо создать собственное промежуточное программное обеспечение, которое перехватывает исключения, выданные промежуточным программным обеспечением переноса JWT, и возвращает ответ 401:
app.Use(next => async context => {
try {
await next(context);
}
catch {
// If the headers have already been sent, you can't replace the status code.
// In this case, throw an exception to close the connection.
if (context.Response.HasStarted) {
throw;
}
context.Response.StatusCode = 401;
}
});
К сожалению, именно так в настоящее время по умолчанию работает промежуточное программное обеспечение JWT/OAuth2 (управляемое MSFT), но в конечном итоге оно должно быть исправлено. Вы можете увидеть этот билет GitHub для получения дополнительной информации: https://github.com/aspnet/Security/issues/411
К счастью, вы можете "легко" обойти это, используя AuthenticationFailed
уведомление:
app.UseOAuthBearerAuthentication(options => {
options.Notifications = new OAuthBearerAuthenticationNotifications {
AuthenticationFailed = notification => {
notification.HandleResponse();
return Task.FromResult<object>(null);
}
};
});