#c# #asp.net-core #identityserver4 #openid-connect
#c# #asp.net-core #identityserver4 #openid-connect
Вопрос:
Я знаю, что об этой проблеме сообщалось много, и есть много статей о том, как это исправить. Я прошел через многие из них и до сих пор не могу решить эту проблему.
Я устанавливаю пользовательские утверждения Principal.Identity
для OnSecurityTokenValidated
обратного вызова на сервере идентификации следующим образом:
public async Task SecurityTokenValidated(SecurityTokenValidatedContext context) {
var identity = context.Principal.Identity as ClaimsIdentity;
foreach(var claim in context.Principal.Claims.Where(x = >x.Type == "adGroupClaimType").ToList()) {
var groupName = Configuration.GetSection("ClaimMappings").GetValue < string > ($ "Prefix_{claim.Value}");
if (!string.IsNullOrWhiteSpace(groupName)) {
identity.AddClaim(new Claim(ClaimTypes.Role, groupName));
}
identity.RemoveClaim(claim);
}
}
Ниже приведена конфигурация, которую я использую на сервере идентификации:
public static IEnumerable < IdentityResource > IdentityResources = >new List < IdentityResource > {
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", new[] {
ClaimTypes.Role
})
};
public static IEnumerable < ApiScope > ApiScopes = >new List < ApiScope > {
new ApiScope("api", "API")
};
public static IEnumerable < Client > Clients = >new List < Client > {
new Client {
ClientId = "mvc-openid",
ClientSecrets = {
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RedirectUris = {
"https://localhost:6001/signin-oidc"
},
AllowedScopes = new List < string > {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api",
"roles"
},
RequirePkce = false,
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true
}
};
Существует клиент MVC, который подключается к серверу идентификации с помощью OpenIdConnect. Код приведен ниже:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(options = >{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
}).AddCookie(options = >{
options.ExpireTimeSpan = 15;
options.SlidingExpiration = true;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
}).AddOpenIdConnect("oidc", options = >{
options.Authority = "https://localhost:5001";
options.ClientId = "mvc-openid";
options.ClientSecret = "secret";
options.ResponseType = "code id_token token";
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.Scope.Add("api");
options.Scope.Add("roles");
options.Scope.Add("offline_access");
options.Events.OnTokenValidated = OnTokenValidated;
options.TokenValidationParameters = new TokenValidationParameters {
NameClaimType = ClaimTypes.Name,
RoleClaimType = ClaimTypes.Role
};
options.ClaimActions.MapUniqueJsonKey(ClaimTypes.Role, ClaimTypes.Role);
});
}
private Task OnTokenValidated(TokenValidatedContext context) {
var t = context.Principal.Claims;
return Task.CompletedTask;
}
Когда я проверяю утверждения внутри OnTokenValidated
, я вижу, что все утверждения о роли, которые я установил с сервера идентификации, отсутствуют. Может кто-нибудь сказать мне, где я ошибаюсь? Я перепробовал почти все, что было найдено в потоках переполнения стека по этой проблеме. Прямо сейчас я понятия не имею, что делать дальше.
Комментарии:
1. добавьте AlwaysIncludeUserClaimsInIdToken = true в конфигурацию вашего клиента и убедитесь, что это добавит утверждения в ваш access_token
2. @mohammadmahdiTalachi сделал это. Это не имеет никакого значения.
Ответ №1:
Я тоже пока нашел только это решение.
options.Events.OnUserInformationReceived = context =>
{
var roleElement = context.User.RootElement.GetProperty("role");
var claims = new List<Claim>();
if (roleElement.ValueKind == System.Text.Json.JsonValueKind.Array)
{
foreach (var r in roleElement.EnumerateArray())
claims.Add(new Claim(JwtClaimTypes.Role, r.GetString()));
}
else
{
claims.Add(new Claim(JwtClaimTypes.Role, roleElement.GetString()));
}
var id = context.Principal.Identity as ClaimsIdentity;
id.AddClaims(claims);
return Task.CompletedTask;
};