本文介绍了MVC6 应用程序中的 OAuth 令牌过期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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.SecurityTokenExpiredExceptionIDX10223:生命周期验证失败.令牌已过期.

我对 OAuth 和一般的 Web API 保护还很陌生,所以我可能有点偏离基础,但是对于过期的令牌,500 错误似乎不适合我.对于 Web 服务客户端来说,这绝对是不友好的.

这是预期的行为吗?如果不是,我需要做些什么才能得到更合适的响应?

解决方案

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

注意:此解决方法不适用于 ASP.NET 5 RC1由于这个其他错误.您可以迁移到 RC2 每晚构建,也可以创建一个自定义中间件来捕获 JWT 不记名中间件抛出的异常并返回 401 响应:

app.Use(next => async context => {尝试 {等待下一个(上下文);}抓住 {//如果头信息已经发送,则不能替换状态码.//在这种情况下,抛出异常关闭连接.如果(context.Response.HasStarted){扔;}context.Response.StatusCode = 401;}});

遗憾的是,这就是 JWT/OAuth2 不记名中间件(由 MSFT 管理)当前默认工作的方式,但最终应该修复它.您可以查看此 GitHub 票以获得更多信息:https://github.com/aspnet/Security/issues/411

幸运的是,您可以通过使用 AuthenticationFailed 通知轻松"解决这个问题:

app.UseOAuthBearerAuthentication(options => {options.Notifications = 新的 OAuthBearerAuthenticationNotifications {AuthenticationFailed = 通知 =>{通知.处理响应();return Task.FromResult(null);}};});

So I have an MVC6 app that includes an identity server (using ThinkTecture's IdentityServer3) and an MVC6 web services application.

In the web services application I am using this code in Startup:

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

Then I have a controller with an action that has the Authorize attribute.

I have a JavaScript application that authenticates with the identity server, and then uses the provided JWT token to access the web services action.

This works, and I can only access the action with a valid token.

The problem comes when the JWT has expired. What I'm getting is what appears to be a verbose ASP.NET 500 error page, that returns exception information for the following exception:

I am fairly new to OAuth and securing Web APIs in general, so I may be way off base, but a 500 error doesn't seem appropriate to me for an expired token. It's definitely not friendly for a web service client.

Is this the expected behavior, and if not, is there something I need to do to get a more appropriate response?

解决方案

Edit: this bug was fixed in ASP.NET Core RC2 and the workaround described in this answer is no longer needed.


Note: this workaround won't work on ASP.NET 5 RC1, due to this other bug. You can either migrate to the RC2 nightly builds or create a custom middleware that catches the exceptions thrown by the JWT bearer middleware and returns a 401 response:

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;
    }
});


Sadly, that's how the JWT/OAuth2 bearer middleware (managed by MSFT) currently works by default, but it should be eventually fixed. You can see this GitHub ticket for more information: https://github.com/aspnet/Security/issues/411

Luckily, you can "easily" work around that by using the AuthenticationFailed notification:

app.UseOAuthBearerAuthentication(options => {
    options.Notifications = new OAuthBearerAuthenticationNotifications {
        AuthenticationFailed = notification => {
            notification.HandleResponse();

            return Task.FromResult<object>(null);
        }
    };
});

这篇关于MVC6 应用程序中的 OAuth 令牌过期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 10:23