MVC6 应用程序中的 OAuth 令牌过期
OAuth token expiration in MVC6 app
所以我有一个 MVC6 应用程序,其中包括一个身份服务器(使用 ThinkTecture 的 IdentityServer3)和一个 MVC6 网络服务应用程序。
在 Web 服务应用程序中,我在 Startup 中使用此代码:
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 错误页面,returns 以下异常的异常信息:
System.IdentityModel.Tokens.SecurityTokenExpiredException
IDX10223: Lifetime validation failed. The token is expired.
总的来说,我对 OAuth 和保护 Web API 还比较陌生,所以我可能离题太远了,但是对于过期的令牌,500 错误似乎不适合我。对web服务客户端肯定不友好。
这是预期的行为吗?如果不是,我是否需要做些什么才能得到更合适的回应?
编辑:此错误已在 ASP.NET Core RC2 中修复,不再需要此答案中描述的解决方法。
注意:此解决方法不适用于 ASP.NET 5 RC1、due to this other bug。您可以迁移到 RC2 每晚构建或创建一个自定义中间件来捕获 JWT 承载中间件抛出的异常和 returns 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
幸运的是,您可以 "easily" 使用 AuthenticationFailed
通知来解决这个问题:
app.UseOAuthBearerAuthentication(options => {
options.Notifications = new OAuthBearerAuthenticationNotifications {
AuthenticationFailed = notification => {
notification.HandleResponse();
return Task.FromResult<object>(null);
}
};
});
所以我有一个 MVC6 应用程序,其中包括一个身份服务器(使用 ThinkTecture 的 IdentityServer3)和一个 MVC6 网络服务应用程序。
在 Web 服务应用程序中,我在 Startup 中使用此代码:
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 错误页面,returns 以下异常的异常信息:
System.IdentityModel.Tokens.SecurityTokenExpiredException IDX10223: Lifetime validation failed. The token is expired.
总的来说,我对 OAuth 和保护 Web API 还比较陌生,所以我可能离题太远了,但是对于过期的令牌,500 错误似乎不适合我。对web服务客户端肯定不友好。
这是预期的行为吗?如果不是,我是否需要做些什么才能得到更合适的回应?
编辑:此错误已在 ASP.NET Core RC2 中修复,不再需要此答案中描述的解决方法。
注意:此解决方法不适用于 ASP.NET 5 RC1、due to this other bug。您可以迁移到 RC2 每晚构建或创建一个自定义中间件来捕获 JWT 承载中间件抛出的异常和 returns 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
幸运的是,您可以 "easily" 使用 AuthenticationFailed
通知来解决这个问题:
app.UseOAuthBearerAuthentication(options => {
options.Notifications = new OAuthBearerAuthenticationNotifications {
AuthenticationFailed = notification => {
notification.HandleResponse();
return Task.FromResult<object>(null);
}
};
});