使用 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 进行自定义生命周期验证

Posted

技术标签:

【中文标题】使用 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 进行自定义生命周期验证【英文标题】:Custom Lifetime Validation With AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 【发布时间】:2016-03-15 08:10:20 【问题描述】:

我正在使用 Visual Studio 2015 Enterprise Update 1 和 ASP.NET vNext rc1-update1 来发布和使用 JWT 令牌,如 here 所述。

在我们的实现中,我们希望控制令牌生命周期验证。

我们尝试了几种方法,所有这些方法都有不良的副作用。例如,在一次尝试中,我们在 Configure 方法中接管了 TokenValidationParameters.TokenValidationParameters.LifetimeValidator 事件:

app.UseJwtBearerAuthentication
(
    options => 
    
        options.TokenValidationParameters = new TokenValidationParameters()
        
            LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
            
                // Pretend to do custom validation
                return false;
            
        ;
    
);

该事件导致验证失败,但客户端收到 500 错误,而我们希望返回 400 系列错误和一个小负载。

在另一次尝试中,我们尝试了 TokenValidationParameters.Events 的各种实现,例如检查 ValidatedToken 事件中的声明,但发现我们无法阻止中间件调用控制器操作,除非引发异常,导致我们回到 500 错误问题。

所以我的问题是:

使用 OIDC 接管生命周期验证的最佳实践是什么?

我们是否可以强制 OIDC 不在令牌中包含某些生命周期声明,例如“nbf”,因为我们无论如何都不需要它们?

【问题讨论】:

【参考方案1】:

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


这是一个known bug。可悲的是,the workaround you could use in beta8 不再有效 in RC1。

您唯一的选择是编写一个捕获异常的中间件,以防止服务器返回 500 响应。当然,它很丑陋并且可能会隐藏重要的异常,但它是唯一适用于 RC1 的已知解决方法。

这是一个例子(确保在 JWT 承载中间件之前注册它):

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

【讨论】:

谢谢,@Pinpoint。您能否告诉我我们是否可以控制 OIDC 生成的令牌中包含哪些生命周期声明?比如我们可以去掉“iat”、“nbf”等吗? 您无法直接访问这些非用户声明,但有更好的方法来控制 OIDC 服务器颁发的令牌的生命周期:最简单的方法是通过选项(通过更新AccessTokenLifetime/IdentityTokenLifetime/RefreshTokenLifetime)。另一种是通过SerializeAccessToken 事件,您可以在其中更新与身份验证票证关联的IssuedUtc/ExpiresUtc 属性(通过context.AuthenticationTicket.Properties)。 对于其他阅读这些 cmets 的人,我们发现在上面的示例代码中捕获 SecurityTokenInvalidLifetimeException 完全符合我们的需求。 为避免在访问令牌过期时出现 500 响应,捕获 SecurityTokenInvalidLifetimeException 将起作用。但是当访问令牌格式错误或被更改时,安全令牌处理程序也会引发其他类型的异常(如InvalidOperationException)。

以上是关于使用 AspNet.Security.OpenIdConnect.Server (ASP.NET vNext) 进行自定义生命周期验证的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)