AspNetCore.Authentication.JwtBearer 失败,没有可用于 .net core RC2 令牌的 SecurityTokenValidator

AspNetCore.Authentication.JwtBearer fails with No SecurityTokenValidator available for token with .net core RC2

我正在尝试使用 AspNew.Security.OpenIdConnect.Server 发布令牌并使用 Microsoft.AspNetCore.Authentication.JwtBearer.

进行验证,让一个简单的端点正常工作并使用 JWT 令牌

我可以很好地生成令牌,但尝试验证令牌失败并出现错误 Bearer was not authenticated. Failure message: No SecurityTokenValidator available for token: {token}

至此,我已经删除了所有内容并具有以下内容:

project.json

{
  "dependencies": {
    "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
    "AspNet.Security.OAuth.Validation": "1.0.0-alpha1-final",
    "AspNet.Security.OpenIdConnect.Server": "1.0.0-beta5-final",
    "Microsoft.AspNetCore.Authentication": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0-rc2-final"
  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": {
      "version": "1.0.0-preview1-final",
      "imports": "portable-net45+win8+dnxcore50"
    }
  },

  "frameworks": {
    "net461": { }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "Views",
      "appsettings.json",
      "web.config"
    ]
  },

  "scripts": {
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

Startup.cs 方法:

// This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthorization(options =>
                {
                    options.AddPolicy(JwtBearerDefaults.AuthenticationScheme,
                        builder =>
                        {
                            builder.
                            AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
                            RequireAuthenticatedUser().
                            Build();
                        }
                    );
                }
            );

            services.AddAuthentication();
            services.AddDistributedMemoryCache();
            services.AddMvc();
            services.AddOptions();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            var jwtOptions = new JwtBearerOptions()
            {
                AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme,
                AutomaticAuthenticate = true,
                Authority = "http://localhost:5000/",
                Audience = "http://localhost:5000/",
                RequireHttpsMetadata = false
            };

            jwtOptions.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>
                (
                    metadataAddress: jwtOptions.Authority + ".well-known/openid-configuration",
                    configRetriever: new OpenIdConnectConfigurationRetriever(),
                    docRetriever: new HttpDocumentRetriever { RequireHttps = false }
                );


            app.UseJwtBearerAuthentication(jwtOptions);

            app.UseOpenIdConnectServer(options =>
            {
                options.AllowInsecureHttp = true;
                options.AuthorizationEndpointPath = Microsoft.AspNetCore.Http.PathString.Empty;
                options.Provider = new OpenIdConnectServerProvider
                {
                    OnValidateTokenRequest = context =>
                    {
                        context.Skip();
                        return Task.FromResult(0);
                    },

                    OnGrantResourceOwnerCredentials = context =>
                    {
                        var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
                        identity.AddClaim(ClaimTypes.NameIdentifier, "[unique id]");

                        identity.AddClaim("urn:customclaim", "value", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken);

                        var ticket = new AuthenticationTicket(
                            new ClaimsPrincipal(identity),
                            new Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties(),
                            context.Options.AuthenticationScheme);

                        ticket.SetScopes("profile", "offline_access");

                        context.Validate(ticket);

                        return Task.FromResult(0);
                    }
                };
            });            

            app.UseMvc();
        }

将 x-url 编码的 POST 发送到 http://localhost:5000 并使用 grant_type=password, username=foo, password=bar 生成预期的 access_token .

我已将 [Authorize("Bearer")] 属性添加到 ValuesController 中,这在调用 JwtBearerMiddlewear 时按预期工作,但我无法获取要验证的令牌。

有没有人在 .net core RC2 上使用它?我在 RC1 上做了同样的事情,但一直无法进行。

谢谢。

从 beta5 开始(针对 ASP.NET Core RC2),the OpenID Connect server middleware no longer uses JWT as the default format for access tokens。相反,它使用不透明的令牌,由坚如磐石的 ASP.NET 核心数据保护堆栈加密(与身份验证 cookie 完全一样)。

您有 3 个选项来修复您看到的错误:

  • 使用开发的 new OAuth2 validation middleware 支持不透明令牌(推荐选项,如果您的 API 和您的授权服务器是同一应用程序的一部分) .为此,请保留 project.json 中的 AspNet.Security.OAuth.Validation 引用,并将 app.UseJwtBearerAuthentication(...) 替换为 app.UseOAuthValidation()。您还可以从 project.json.
  • 中删除 Microsoft.AspNetCore.Authentication.JwtBearer

  • 通过在选项中调用 options.AccessTokenHandler = new JwtSecurityTokenHandler(); 强制 OpenID Connect 服务器中间件使用 JWT 令牌。请注意,您还必须调用 ticket.SetResources(...) 以将适当的受众附加到 JWT 令牌(有关更多信息,请参阅其他 )。

  • 使用new introspection middleware。此选项更复杂,需要实施 ValidateIntrospectionRequest 事件来验证客户端凭据。仅当您知道自己在做什么时才使用它。

旁注,如果有人遇到同样的错误(没有可用于令牌的 SecurityTokenValidator):

仔细检查客户端发送的身份验证 header 的格式是否正确:

Authorize: Bearer [ey....]

No SecurityTokenValidator available for token 错误 表示没有为请求中找到的授权格式 header 注册处理程序。例如,如果收到的请求包含 header 值“Bearer Bearer ey82383...”,或者“Bearer”关键字被省略或拼写错误,您将遇到此错误。