从 ASP.NET vNext beta5 移动到 beta7 后 JWT Bearer 令牌身份验证错误

Posted

技术标签:

【中文标题】从 ASP.NET vNext beta5 移动到 beta7 后 JWT Bearer 令牌身份验证错误【英文标题】:JWT Bearer token authentication error after moving from ASP.NET vNext beta5 to beta7 【发布时间】:2015-12-15 11:06:02 【问题描述】:

我从 beta5 迁移到 beta7 ASP.NET vNext,当我尝试使用无效的 JWT 令牌或根本没有令牌访问受保护的 API 控制器时出现以下错误:

InvalidOperationException:以下身份验证方案不是 公认: Microsoft.AspNet.Http.Authentication.Internal.DefaultAuthenticationManager.d__10.MoveNext()

如果我尝试使用有效令牌访问受保护的控制器,我可以成功获得响应。

这是我的受保护控制器:

[Authorize]
    [Route("api/protected")]
    public class ProtectedController : Controller
    
        [Route("")]
        public IEnumerable<object> Get()
        
            var identity = User.Identity as ClaimsIdentity;

            return identity.Claims.Select(c => new
            
                Type = c.Type,
                Value = c.Value
            );
        
    

这是我的 Startup 课程:

public class Startup
    
        public Startup(IHostingEnvironment env)
        
        

        public static IConfiguration Configuration  get; set; 

        public void ConfigureServices(IServiceCollection services)
        
            services.AddMvc();
        

        // Configure is called after ConfigureServices is called.
        public void Configure(IApplicationBuilder app, IApplicationEnvironment env)
        
            ConfigureOAuthTokenConsumption(app);
            app.UseMiddleware<StaticFileMiddleware>(new StaticFileOptions());
            app.UseErrorPage();
            app.UseMvc(); 
        

        private void ConfigureOAuthTokenConsumption(IApplicationBuilder app)
        

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseOwin(addToPipeline =>
            
                addToPipeline(next =>
                
                    var appBuilder = new AppBuilder();
                    appBuilder.Properties["builder.DefaultApp"] = next;

                    var issuer = Settings.Issuer;
                    var audience = Settings.Audience;
                    var secret = TextEncodings.Base64Url.Decode(Settings.Secret);


                    appBuilder.UseJwtBearerAuthentication(
                        new JwtBearerAuthenticationOptions
                        
                            AuthenticationMode = AuthenticationMode.Active,
                            AllowedAudiences = new[]  audience ,
                            IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                            
                                new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
                            ,
                        );

                    return appBuilder.Build<AppFunc>();
                );
            );
        
    

当我使用 beta5 时,它运行良好。当我请求没有有效令牌的受保护控制器时,我得到了 401 响应,这是正确的行为。 我需要在 ASP.NET vNext beta7 中更改 JWT 令牌消费配置吗?

【问题讨论】:

我真的很好奇:既然可以使用 ASP.NET 5 的中间件,为什么还要使用 Katana 的 OAuth2/JWT 不记名身份验证中间件? nuget.org/packages/Microsoft.AspNet.Authentication.OAuthBearer/… @Pinpoint,我尝试使用 app.UseOAuthBearerAuthentication(options => options.AutomaticAuthentication = true; options.Audience = Audience; options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(secret); ) 使用令牌;但我收到错误'System.InvalidOperationException:IDX10636:SignatureProviderFactory.CreateForVerifying 为密钥返回 null:'System.IdentityModel.Tokens.SymmetricSecurityKey'。在这种情况下,我也不清楚在哪里设置发行人。 是的,对称密钥尚不支持。也就是说,您应该真正考虑使用非对称密钥,因为它提供了一种更强大的方法。要设置颁发者,只需使用options.Issuer = "issuer" @Pinpoint,我可以看到只有 options.ClaimsIssuer,没有 options.Issuer。这是我需要设置的吗? 糟糕,抱歉,我是options.TokenValidationParameters.ValidIssuer 【参考方案1】:

我测试了代码,我看到 JWT 令牌在没有 [Authorize] 属性。因此,在控制器级别上,用户已通过身份验证并且声明存在。

还有一个与 CORS 设置相关的问题,因为通过 Postman 调用站点工作正常,但是当我从不同域访问它时,我有

以下身份验证方案未被接受:

即使我传递了有效的令牌也会出错。 与AuthorizationFilterAttribute 相同的故事 - 用户始终未在过滤器中进行身份验证,但在操作中可以。

到目前为止,我发现的唯一解决方法是添加 ActionFilterAttribute 并在执行操作之前检查权限

   public override void OnActionExecuting(ActionExecutingContext context)
        

            var principal = context.HttpContext.User.Identity as ClaimsIdentity;

            if (!principal.IsAuthenticated)
            
                context.Result = new HttpUnauthorizedResult();
            


            base.OnActionExecuting(context);
        

此处用户已通过身份验证(如果 JWT 存在且有效),我们没有异常并且可以拒绝请求。

【讨论】:

以上是关于从 ASP.NET vNext beta5 移动到 beta7 后 JWT Bearer 令牌身份验证错误的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET 5 (vNext) 中的身份验证

在 ASP.NET 5 (vNext) MVC 6 中实现自定义路由器

身份验证类型名称如何在 asp.net vnext 中注册

ASP.NET Boilerplate v5升级到Abp vNext的改动

ASP.NET Boilerplate v5升级到Abp vNext的改动

结合CLR类库发布ASP.NET vNext/DNX