Спецификация 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 в желаемый тип заявки, но не знаете где?
http://schemas.microsoft.com/ws/2008/06/identity/claims/role этот тип специфичен для Microsoft .. и это стандартные претензии http://openid.net/specs/openid-connect -core-1_0.html # Претензии – LP13