在ASP.NET 5中使用声明与OpenIdConnect.Server

在过去的7天里,我尝试使用OpenIdConnect.Server和资源所有者流来设置ASP.NET 5 WebApi。

我在生成令牌和访问[Authorize]受保护的操作方面或多或少成功。

但是,当我尝试访问this.User.Identity.Claims ,它是空的。 我现在使用的是ASP.NET 5,beta6(升级到最近的beta7并等待它正式发布时遇到麻烦)

在Startup.cs中我得到了以下内容:

 public void ConfigureServices(IServiceCollection services) { services.AddCaching(); services.AddEntityFramework() .AddSqlServer() .AddDbContext(options => { options.UseSqlServer(Configuration.Get("Data:DefaultConnection:ConnectionString")); }); services.AddIdentity( options => options.User = new Microsoft.AspNet.Identity.UserOptions { RequireUniqueEmail = true, UserNameValidationRegex = "^[a-zA-Z0-9@_\\.-]+$" }) .AddEntityFrameworkStores() .AddDefaultTokenProviders(); services.ConfigureCors(configure => { configure.AddPolicy("CorsPolicy", builder => { builder.WithOrigins("http:/localhost/", "http://win2012.bludev.com/"); }); }); services.AddScoped(); } public void Configure(IApplicationBuilder app) { var factory = app.ApplicationServices.GetRequiredService(); factory.AddConsole(); app.UseStaticFiles(); app.UseOAuthBearerAuthentication(options => { options.Authority = "http://win2012.bludev.com/api/auth/"; options.Audience = "http://win2012.bludev.com/"; options.AutomaticAuthentication = true; options.TokenValidationParameters = new TokenValidationParameters() { RequireExpirationTime = true, RequireSignedTokens = true, RoleClaimType = ClaimTypes.Role, NameClaimType = ClaimTypes.NameIdentifier, ValidateActor = true, ValidateAudience = false, ValidateIssuer = true, ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidateSignature = true, ValidAudience = "http://win2012.bludev.com/", ValidIssuer = "http://win2012.bludev.com/" }; }); app.UseOpenIdConnectServer(options => { options.Issuer = new Uri("http://win2012.bludev.com/api/auth/"); options.AllowInsecureHttp = true; options.AuthorizationEndpointPath = PathString.Empty; options.Provider = new AuthorizationProvider(); options.ApplicationCanDisplayErrors = true; // Note: in a real world app, you'd probably prefer storing the X.509 certificate // in the user or machine store. To keep this sample easy to use, the certificate // is extracted from the Certificate.pfx file embedded in this assembly. options.UseCertificate( assembly: typeof(Startup).GetTypeInfo().Assembly, resource: "AuthExample.Certificate.pfx", password: "Owin.Security.OpenIdConnect.Server"); }); app.UseIdentity(); app.UseMvc(); } } 

我使用了app.UseOAuthBearerAuthentication因为我无法使app.UseOpenIdConnectAuthentication正常工作,我只能在控制台中获取:

request:/ admin / user / warning:[Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OIDCH_0004:OpenIdConnectAuthenticationHandler:message.State为null或空。 请求:/.well-known/openid-configuration warning:[Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OIDCH_0004:OpenIdConnectAuthenticationHandler:message.State为null或为空。

和超时后的例外情况

错误:[Microsoft.AspNet.Server.WebListener.MessagePump] ProcessRequestAsync System.InvalidOperationException:IDX10803:无法创建以从以下位置获取配置:’ http ://win2012.bludev.com/api/auth/.well-known/openid – 配置 ‘。 at Microsoft.IdentityModel.Logging.LogHelper.Throw(String message,Type excep tionType,EventLevel logLevel,Exception innerException)at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext()—来自先前位置的堆栈跟踪结束抛出exception的地方—在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)中…

使用此配置UseOpenIdConnectAuthentication

 app.UseOpenIdConnectAuthentication(options => { options.AuthenticationScheme = OpenIdConnectAuthenticationDefaults.AuthenticationScheme; options.Authority = "http://win2012.bludev.com/api/auth/"; options.Audience = "http://win2012.bludev.com/"; options.Resource = "http://win2012.bludev.com/"; options.AutomaticAuthentication = true; options.TokenValidationParameters = new TokenValidationParameters() { RequireExpirationTime = true, RequireSignedTokens = true, RoleClaimType = ClaimTypes.Role, NameClaimType = ClaimTypes.NameIdentifier, ValidateActor = true, ValidateAudience = false, ValidateIssuer = true, ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidateSignature = true }; }); 

所以真正的问题是:

  1. 如何让资源所有者流程处理索赔
  2. ValidateLifetime = trueValidateAudience = true将抛出exception并导致Http Code 500响应而没有打印错误。
  3. 如何将身份validation失败转换为有意义的400/403代码,json或xml响应(取决于客户端首选项)为用户显示? (在这种情况下,JavaScript是客户端)?

app.UseOpenIdConnectAuthentication() (依赖于OpenIdConnectAuthenticationMiddleware )仅用于支持交互式流(代码/隐式/混合),不能与资源所有者密码凭据授权类型一起使用。 由于您只想validation访问令牌,请改用app.UseOAuthBearerAuthentication()

有关ASP.NET 5中不同OpenID Connect / OAuth2中间件的更多信息,请参阅此SO答案: 配置授权服务器端点

如何让资源所有者流程处理索赔

您使用的整个OpenIdConnectServerMiddleware都基于声明。

如果您在序列化特定声明时遇到问题,请记住,除了ClaimTypes.NameIdentifier之外的所有声明都不会在标识和访问令牌中默认序列化,因为它们都可由客户端应用程序和用户代理读取。 为避免泄露机密数据,您需要指定一个显式destination指明您希望序列化声明的位置:

 // This claim will be only serialized in the access token. identity.AddClaim(ClaimTypes.Name, username, OpenIdConnectConstants.Destinations.AccessToken); // This claim will be serialized in both the identity and the access tokens. identity.AddClaim(ClaimTypes.Surname, "Doe", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken);); 

ValidateLifetime = true或ValidateAudience = true将抛出exception并导致Http Code 500响应而没有打印错误。

如何将身份validation失败转换为有意义的400/403代码,json或xml响应(取决于客户端首选项)为用户显示? (在这种情况下,JavaScript是客户端)?

这就是OIDC客户端中间件(由MSFT管理)目前默认工作的方式,但它最终会被修复。 您可以看到此GitHub票证是一种解决方法: https : //github.com/aspnet/Security/issues/411