4

在過去的7天中,我嘗試使用OpenIdConnect.Server和資源所有者流設置ASP.NET 5 WebApi。在ASP.NET 5中使用OpenIdConnect.Server的聲明

我在生成令牌和訪問[Authorize]受保護的操作方面或多或少成功。

但是,當我嘗試訪問this.User.Identity.Claims時,它是空的。我使用ASP.NET 5,beta6現在(在遇到問題時升級到最新的β7的,等待它的正式發佈)

在Startup.cs我有以下幾點:

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddCaching(); 

    services.AddEntityFramework() 
     .AddSqlServer() 
     .AddDbContext<AuthContext>(options => 
     { 
      options.UseSqlServer(Configuration.Get("Data:DefaultConnection:ConnectionString")); 
     }); 

    services.AddIdentity<AuthUser, AuthRole>(
     options => options.User = new Microsoft.AspNet.Identity.UserOptions 
     { 
      RequireUniqueEmail = true, 
      UserNameValidationRegex = "^[[email protected]_\\.-]+$" 
     }) 
     .AddEntityFrameworkStores<AuthContext, Guid>() 
     .AddDefaultTokenProviders(); 

    services.ConfigureCors(configure => 
    { 
     configure.AddPolicy("CorsPolicy", builder => 
     { 
      builder.WithOrigins("http:/localhost/", "http://win2012.bludev.com/"); 
     }); 
    }); 

    services.AddScoped<IAuthRepository, AuthRepository>(); 
} 

    public void Configure(IApplicationBuilder app) 
    { 
     var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>(); 
     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工作,所有我會得到這是在控制檯:

要求:/管理/用戶/警告: [Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OI DCH_0004:OpenIdConnectAuthenticationHandler: message.State爲空或空。請求: /.well-known/openid-configuration警告: [Microsoft.AspNet.Authentication.OpenIdConnect.OpenIdConnectAuthentica tionMiddleware] OIDCH_0004:OpenIdConnectAuthenticationHandler: message.State是空值或空白。

且超時後一個異常

錯誤:[Microsoft.AspNet.Server.WebListener.MessagePump] ProcessRequestAsync System.InvalidOperationException:IDX10803:無法 創建從獲得configura和灰: 'http://win2012.bludev.com/api/auth/.well-known/openid-configuration' 。在Microsoft.IdentityModel.Logging.LogHelper.Throw(字符串 消息類型excep tionType,EventLevel日誌級別,異常 的InnerException)在 Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext() ---堆完從先前的位置在那裏異常被拋出在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot ification跟蹤---在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任務 任務)(任務task) ...

有了這個配置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會拋出異常,並導致HTTP代碼500響應,從而打印出錯誤的工作。
  3. 如何將身份驗證失敗轉化爲有意義的400/403代碼和json或xml響應(取決於客戶端首選項)以供用戶顯示? (在這種情況下JavaScript是客戶端)?
+0

'InvalidOperationException'是由'http:// win2012.bludev.com/api/auth /'沒有服務器引起的。當OAuth2承載中間件嘗試下載提供程序的配置元數據時,它會崩潰並返回一個異常。 – Pinpoint

回答

2

app.UseOpenIdConnectAuthentication()(其依賴於OpenIdConnectAuthenticationMiddleware)僅意在支持交互流(編碼/隱式/混合),並不能與資源所有者密碼憑證授予類型使用。由於您只想驗證訪問令牌,請改用app.UseOAuthBearerAuthentication()

看到這個ASP.NET 5 SO回答有關不同ID連接/ OAuth2用戶中間件的更多信息:Configure the authorization server endpoint

如何獲得資源所有者與流動索賠

整個工作您使用的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 =真會拋出異常,並導致一個Http代碼500響應沒有打印錯誤。

如何把認證失敗成有意義403分之400碼和要被顯示用於用戶的JSON或XML階躍響應(根據客戶端偏好)? (在這種情況下JavaScript是客戶端)?

這就是OIDC客戶端中間件(由MSFT管理)目前默認工作的方式,但它最終會被修復。你可以看到這個GitHub票證的解決方法:https://github.com/aspnet/Security/issues/411

+0

感謝它像一個魅力工作。在我使用identity.AddClaim之前(新的Claim(ClaimTypes.Name,username));'。假設我會有更多數量的索賠(由'用戶'和行動'創建','更新','AssignRoles'等組織組織),並且不希望將它們全部放入jwt令牌(對於這兩個令牌大小和機密性),但仍然需要他們的服務器支持authorizatoin,我需要創建一個從服務器(或Redis緩存)中獲取它們的中間件嗎?或者要走的路是什麼 – Tseng