MVC6应用中的OAuth令牌到期

时间:2015-08-31 23:45:58

标签: oauth-2.0 asp.net-core jwt identityserver3

所以我有一个MVC6应用程序,其中包括一个身份服务器(使用ThinkTecture的IdentityServer3)和一个MVC6 Web服务应用程序。

在Web服务应用程序中,我在启动时使用此代码:

app.UseOAuthBearerAuthentication(options =>
{
    options.Authority = "http://localhost:6418/identity";
    options.AutomaticAuthentication = true;
    options.Audience = "http://localhost:6418/identity/resources";
});

然后我有一个控制器,其动作具有Authorize属性。

我有一个JavaScript应用程序,它使用身份服务器进行身份验证,然后使用提供的JWT令牌来访问Web服务操作。

这样可行,我只能使用有效令牌访问该操作。

问题出现在JWT过期时。我得到的似乎是一个详细的ASP.NET 500错误页面,它返回以下异常的异常信息:

  

System.IdentityModel.Tokens.SecurityTokenExpiredException   IDX10223:终身验证失败。令牌已过期。

我对OAuth很新,并且通常保护Web API,所以我可能会偏离基础,但对于过期的令牌来说,500错误对我来说似乎不合适。它对于Web服务客户端来说绝对不友好。

这是预期的行为,如果不是,我需要做些什么来获得更合适的回应?

1 个答案:

答案 0 :(得分:11)

编辑:此错误已在ASP.NET Core RC2中修复,不再需要此答案中描述的解决方法。

注意:此解决方法不适用于ASP.NET 5 RC1 due to this other bug。您可以迁移到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);
        }
    };
});