Сервер идентификации 4 — Утверждения о роли отсутствуют в обработчике OpenIdConnect в клиенте MVC

#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;
};
 

https://github.com/skoruba/IdentityServer4.Admin/issues/109