2016-10-05 7 views
1

Спецификация OpenidConnect, основанная на стандарте, для заявлений о претензиях на роль и заявки на имя - role и name. Однако в .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()

Update 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); 
    } 

Update 2

Я использую IdentityServer3 для проверки подлинности для всех наших приложений. Если клиентское приложение разработано с использованием классического ASP.NET MVC, то обработчик JWT ASP.NET будет преобразовывать тип входящего role претензии к http://schemas.microsoft.com/ws/2008/06/identity/claims/role(Более подробную информацию можно найти here под Claims Transformation секции)
Однако это не относится, когда клиентское приложение разработанный с использованием ASP.NET Core. Ядро .net НЕ ДОЛЖНО преобразовать искомые типы в тип .Net, и это верно. Однако .Net Core внутренне использует тип заявки .Net, чтобы найти требования к роли пользователя.

Это означает, что мне нужно преобразовать типы претензий .Net в желаемый тип заявки, но не знаете где?

ответ

1

Каковы стандартные соглашения? Вы только думаете об этом из контекста спецификации OpenId Connect, которая не является единственным стандартом идентификации. Microsoft сделала его достаточно общим для поддержки всех систем идентификации.

Ошибка здесь, похоже, выполняется в реализации аутентификации 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 # Претензии – LP13

1

В качестве альтернативы вы можете рассмотреть вопрос о помещении промежуточного программного обеспечения для применения соответствующих утверждений о роли, основанных на заявлениях OpenId, возвращающихся назад?

+0

Хорошо, это можно сделать с помощью промежуточного программного обеспечения 'UseClaimsTransformation'. – Brad

+0

Слишком сложно. Роль, имя пользователя, userid и элемент безопасности можно настроить с помощью IdentityOptions – Tseng

+0

Не думаю, что мы можем использовать UseClaimsTransformation. Он позволяет добавлять новые претензии, но вы не можете изменить тип существующих требований в UseClaimsTransformation. – LP13

0

Вы можете настроить типы претензий во время запуска приложения.

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

Вы можете увидеть claim options на GitHub.

+0

не работает. Infact метод никогда не запускается – LP13