Истечение срока действия токена 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);
        }
    };
});
Другие вопросы по тегам