身份服务器4。每个用户使用 2 个角色

IdentityServer4. Using 2 roles per user

我正在使用 IdentityServer4 和 MVC 客户端。我的问题是每个用户只能使用 1 个以上的角色。在下面的示例中,我有 2 个控制器,每个控制器都有其授权。如果 1 个用户在寄存器中有 2 个角色,他将拒绝两个角色的访问。

当您只为用户保留 1 个角色时,它工作得很好

Config.cs (IDS4)

        public static IEnumerable<IdentityResource> Ids =>
        new IdentityResource[]
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
            new IdentityResources.Email(),
            new IdentityResources.Phone(),
            new IdentityResource("role", "role", new List<string> { "role" }),
        };

            new Client
            {
                ClientId = "mvc",
                ClientName = "MVC App",
                ClientSecrets = { new Secret("secret".Sha256()) },
                AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                RequireConsent = false,

                RedirectUris = { mvcURL + "/signin-oidc" },
                FrontChannelLogoutUri = mvcURL + "/signout-oidc",
                PostLogoutRedirectUris = { mvcURL + "/signout-callback-oidc" },

                //AllowOfflineAccess = true,
                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Email,
                    IdentityServerConstants.StandardScopes.Phone,
                    "api", "role"
                }
            },

ProfileService.cs (IDS4)

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);
        var principal = await _claimsFactory.CreateAsync(user);

        var claims = principal.Claims.ToList();
        claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();

        // Add custom claims in token here based on user properties or any other source
        claims.Add(new Claim("id_user", user.Id.ToString()));
        claims.Add(new Claim("name", user.Name));
        claims.Add(new Claim("email", user.Email.ToString()));
        claims.Add(new Claim("role", user.role.ToString()));

        if (_userManager.SupportsUserRole)
        {
            var roles = await _userManager.GetRolesAsync(user);
            foreach (var roleName in roles)
            {
                claims.Add(new Claim(JwtClaimTypes.Role, roleName));

                if (_roleManager.SupportsRoleClaims)
                {
                    var role = await _roleManager.FindByNameAsync(roleName);
                    if (role != null)
                        claims.AddRange(await _roleManager.GetClaimsAsync(role));
                }
            }
        }

        context.IssuedClaims = claims;
    }

Startup.cs (MVC)

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;

        })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {
                options.Authority = Configuration.GetSection("ids_URI").Value;
                options.ClientId = "mvc";
                options.ClientSecret = "secret";
                options.ResponseType = OpenIdConnectResponseType.Code;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("email");
                options.Scope.Add("role");
                options.SaveTokens = true;
                options.ClaimActions.DeleteClaim("sid");
                options.ClaimActions.DeleteClaim("idp");
                options.ClaimActions.MapUniqueJsonKey("role", "role", "role");
                options.TokenValidationParameters.RoleClaimType = "role";
            });

控制器 1 (MVC)

[Authorize(Roles = "CANCELAMENTO")]
public class CancelamentoController : Controller

控制器 2 (MVC)

[Authorize(Roles = "ABASTECIMENTO")]
public class AbastecimentoController : Controller

在 AspNetUserRoles table 我有 2 个用户角色

用户对象来自角色:

Claims [IEnumerable]:{System.Security.Claims.ClaimsPrincipal.<get_Claims>d__22}
 Membros não públicos
Visualização dos Resultados:Expandir a Visualização dos Resultados vai enumerar o IEnumerable
   [0] [Claim]:{s_hash: 6WmMG-GghFBT9LCigeOnnw}
   [1] [Claim]:{sub: 64637127-9e46-46e2-ad51-47297a52d483}
   [2] [Claim]:{auth_time: 1641251760}
   [3] [Claim]:{amr: pwd}
   [4] [Claim]:{name: NOME}  
   [5] [Claim]:{given_name: SOBRENOME}
   [6] [Claim]:{email: NOME@MAIL.COM}
   [8] [Claim]:{role: ["ABASTECIMENTO","CANCELAMENTO"]}

有什么想法吗?

谢谢

我有同样的问题,我改变了

options.ClaimActions.MapUniqueJsonKey("role", "role", "role");

options.ClaimActions.MapJsonKey("role", "role", "role");

用户对象将是这样的:

[8] [Claim]:{role: "ABASTECIMENTO"}
[9] [Claim]:{role: "CANCELAMENTO"}

使用这种方法 User.IsInRole("role name"); 效果很好。

我的 StartUp.cs 在 MVC 中:

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Authority = "https://localhost:5001";
    options.ClientId = "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = "code id_token";
    options.Scope.Add("email");
    options.Scope.Add("roles");

    options.ClaimActions.DeleteClaim("sid");
    options.ClaimActions.DeleteClaim("idp");
    options.ClaimActions.DeleteClaim("s_hash");
    options.ClaimActions.DeleteClaim("auth_time");
    options.ClaimActions.MapJsonKey("role", "role");
    options.Scope.Add("api1");
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = "name",
        RoleClaimType = "role"
    };
});

Config.cs 在 IDS4 中:

public static class Config
{
    public static IEnumerable<IdentityResource> IdentityResources =>
        new List<IdentityResource>
        {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResources.Email(),
        new IdentityResource("roles", "Your role(s)", new List<string>() { "role" })
        };


    public static IEnumerable<ApiScope> ApiScopes =>
        new List<ApiScope>
        {
            new ApiScope("api1", "My API")
        };

    public static IEnumerable<Client> Clients =>
        new List<Client>
        {
        new Client
        {
            ClientId = "mvc",
            ClientName = "Application Web",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets = { new Secret("secret".Sha256()) },
            RequirePkce = false,
            AllowRememberConsent = false,
            RedirectUris = { "https://localhost:5003/signin-oidc" },

            PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" },

            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                "api1",
                "roles"
            }
        }
        };
}