2016-10-05 62 views
1

基於OpenIDConnect規範,角色聲明和名稱聲明的標準類型是rolename。但在.net核心System.Security.Claims.ClaimsIdentity.NameClaimType設置爲「http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name」和System.Security.Claims.ClaimsIdentity.RoleClaimType設置爲「http://schemas.microsoft.com/ws/2008/06/identity/claims/role爲什麼.Net Core有自己的聲明類型?

我的問題在這裏是與角色。

我的ASP.NET核心應用程序使用OpenIdConnect進行身份驗證。成功驗證後,OpenIdConnect提供商將該角色作爲索賠集合的一部分發回,其中Cliam.Type設置爲role,根據OpenId規範這是正確的。

但是由於.Net Core有自己的角色類型,IsInRole()方法總是返回false。因爲我認爲IsInRole()方法使用Microsoft的角色類型進行比較。

爲什麼.net使用不同類型的索賠而不是使用標準約定?和我怎麼解決IsInRole()問題

更新1

嗯,我試着啓動期間配置要求的類型,但沒有奏效。

startup.cs

public class Startup 
{ 
    public Startup(IHostingEnvironment env) 
    { 
     // some stuff here that is not related to Identity like building configuration 
    } 

    public IConfigurationRoot Configuration { get; } 

    // This method gets called by the runtime. Use this method to add services to the container. 
    public void ConfigureServices(IServiceCollection services) 
    { 
     // Add framework services. 
     services.AddApplicationInsightsTelemetry(Configuration); 
     services.AddAuthorization(); 
     services.AddMvc(config => 
     { 
      var policy = new AuthorizationPolicyBuilder() 
      .RequireAuthenticatedUser() 
      .Build(); 
      config.Filters.Add(new AuthorizeFilter(policy)); 
     }); 

     // Add Kendo UI services to the services container 
     services.AddKendo(); 

     // Transform Microsoft cliam types to my claim type 
     services.AddIdentity<ApplicationUser, ApplicationRole>(options => 
     { 
      options.ClaimsIdentity.RoleClaimType = "role"; 
      options.ClaimsIdentity.UserNameClaimType = "name"; 
     }); 

    } 

    // 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, IApplicationLifetime appLifetime) 
    {    
     loggerFactory.AddSerilog(); 
     appLifetime.ApplicationStopped.Register(Log.CloseAndFlush); 
     app.UseExceptionHandler("/Home/Error"); 
     app.UseApplicationInsightsRequestTelemetry(); 
     app.UseApplicationInsightsExceptionTelemetry(); 
     app.UseStaticFiles(); 

     app.UseIdentityServer(Configuration["Identity:Authority"], Configuration["Identity:ClientId"], Configuration["Identity:PostLogoutRedirectUri"]); 

     app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 

     // Configure Kendo UI 
     app.UseKendo(env); 
    } 
} 

UseIdentityServer擴展方法

public static void UseIdentityServer(this IApplicationBuilder app, string authority, string clientId, string postlogoutRedirectUri) 
    { 
     app.UseCookieAuthentication(new CookieAuthenticationOptions() 
     { 
      AutomaticAuthenticate = true, 
      AutomaticChallenge = true, 
      AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme, 
      LoginPath = IdentityConstant.CallbackPath, 
      AccessDeniedPath = new PathString(IdentityConstant.AccessDeniedPath), 
      CookieName = IdentityConstant.AuthenticationCookieName, 
     }); 

     JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>(); 

     var connectOptions = new OpenIdConnectOptions() 
     {   
      AutomaticChallenge = true, 
      Authority = authority, 
      ClientId = clientId, 
      ResponseType = IdentityConstant.ResponseType, 
      AuthenticationScheme = IdentityConstant.OpenIdAuthenticationScheme, 
      SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme, 
      PostLogoutRedirectUri = postlogoutRedirectUri, 
      CallbackPath = IdentityConstant.CallbackPath, 
      Events = new OpenIdConnectEvents() 
      { 
       OnTokenValidated = async context => 
       { 
        var userInfoClient = new UserInfoClient(context.Options.Authority + IdentityConstant.UserInfoEndpoint); 
        var response = await userInfoClient.GetAsync(context.ProtocolMessage.AccessToken); 
        var claims = response.Claims; 

        //We will create new identity to store only required claims. 
        var newIdentity = new ClaimsIdentity(context.Ticket.Principal.Identity.AuthenticationType); 

        // keep the id_token for logout 
        newIdentity.AddClaim(new Claim(IdentityConstant.IdTokenClaim, context.ProtocolMessage.IdToken)); 

        // add userinfo claims 
        newIdentity.AddClaims(claims); 

        // overwrite existing authentication ticket 
        context.Ticket = new AuthenticationTicket(
         new ClaimsPrincipal(newIdentity), 
         context.Ticket.Properties, 
         context.Ticket.AuthenticationScheme); 

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

     connectOptions.Scope.Add(IdentityConstant.OpenIdScope); 
     connectOptions.Scope.Add(IdentityConstant.ProfileScope); 
     connectOptions.Scope.Add("roles"); 

     app.UseOpenIdConnectAuthentication(connectOptions); 
    } 

更新2

我用IdentityServer3爲我們所有的應用程序的認證。如果客戶端應用程序使用經典的ASP.NET MVC開發的,那麼ASP.Net的智威湯遜處理程序將轉換傳入role要求類型http://schemas.microsoft.com/ws/2008/06/identity/claims/role(更多細節可以在Claims Transformation節中找到here)時,客戶端應用程序
然而同樣是不正確的使用ASP.NET Core開發。 .net核心不會將索賠類型轉換爲.Net索賠類型,這是正確的。但是.Net Core內部使用.Net聲明類型來查找用戶的角色聲明。

這意味着我需要將.Net聲明類型轉換爲期望的聲明類型,但不知道在哪裏?

回答

1

什麼是標準約定?你只是從OpenId Connect規範的背景來考慮它,而OpenId Connect規範並不是那裏唯一的身份標準。微軟已經足夠支持所有身份系統。

這裏的錯誤似乎是在OpenId Connect身份驗證實現中,因爲它沒有提供ClaimsPrincipal,它使用角色的正確聲明類型。

儘管如此,您可以通過實施您自己的ClaimsPrincipal並覆蓋IsInRole()方法來使用正確的聲明類型來解決此問題。

+0

http://schemas.microsoft.com/ws/2008/06/identity/claims/role這種類型是特定於Microsoft ..這些是標準聲明http://openid.net/specs/openid-connect -core-1_0.html#Claims – LP13

1

另外,你可能會考慮放置一些中間件來應用基於OpenId聲明返回的適當角色聲明?

+0

好點,這可以通過UseClaimsTransformation中間件完成。 – Brad

+0

太複雜了。角色,用戶名,用戶ID和安全性可以通過IdentityOptions配置 – Tseng

+0

我不認爲我們可以使用UseClaimsTransformation。它只允許添加新的聲明,但您無法更改UseClaimsTransformation中現有聲明的類型 – LP13

0

您可以在應用程序啓動過程中配置聲明類型。

services.AddIdentity<ApplicationUser, IdentityRole>(options => { 
     options.ClaimsIdentity.RoleClaimType = "http://yourdesiredclaimtype"; 
     options.ClaimsIdentity.UserNameClaimType = "http://yourdesiredclaimtype"; 
}); 

您可以在GitHub上看到claim options

+0

無效。事實上,這個方法永遠不會被解僱 – LP13

相關問題