IdentityServer4 Role Based Authorization для нескольких ролей - PullRequest
1 голос
/ 05 октября 2019

Я хочу реализовать множественные авторизации на основе ролей с гибридом IdentityServer4, все хорошо, но когда я хочу использовать вот так:

[Authorize(Roles = "Admin,SalaryUser")]

, это не позволяет мне и дает доступ запрещен.

В моем сценарии пользователи имеют несколько ролей, и, если роль действительна, контроллер должен предоставить мне доступ, например, в приведенном выше коде контроллер должен предоставить доступ этим пользователям: пользователи имеют роль SalaryUser,пользователи с ролями администратора, пользователи имеют роли администратора, SalaryUser.

вот конфигурация:

.AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = "Cookies";

                        options.Authority = authority;
                        options.RequireHttpsMetadata = false;
                        options.ClientId = clientId;
                        options.ClientSecret = "secret";
                        options.ResponseType = "code id_token";
                        options.UseTokenLifetime = false;
                        options.SaveTokens = true;
                        options.GetClaimsFromUserInfoEndpoint = true;





                        options.ClaimActions.MapCustomJson("role", jobj =>
                        {
                            IEnumerable<string> values = jobj["http://schemas.microsoft.com/ws/2008/06/identity/claims/role"].Values<string>();
                            StringBuilder sb = new StringBuilder();
                            foreach (string val in values)
                            {
                                sb.Append(val + ",");
                            }
                            return sb.ToString().TrimEnd(',');
                        });

                        options.Scope.Add("api1");
                        options.Scope.Add("offline_access");
                       // options.Scope.Add("roles");

                        options.Events = new OpenIdConnectEvents()
                        {

                            OnUserInformationReceived = async UserInformationReceivedContext =>
                            {
                                // UserInformationReceivedContext.User.Remove("address");

                                if (UserInformationReceivedContext.User.TryGetValue("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", out JToken role))
                                {
                                    var claims = new List<Claim>();
                                    if (role.Type != JTokenType.Array)
                                    {
                                        claims.Add(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", (string)role));
                                    }
                                    else
                                    {
                                        foreach (var r in role)
                                            claims.Add(new Claim("role", (string)r));
                                    }
                                    var id = UserInformationReceivedContext.Principal.Identity as ClaimsIdentity;
                                    id.AddClaims(claims);
                                }
                            }
                        };

                        options.ClaimActions.MapAll();
                    });

Ответы [ 2 ]

0 голосов
/ 07 октября 2019

Вам не нужно вручную сопоставлять заявки с MapCustomJson или в вашем OnUserInformationReceived.

Если утверждение в токене jwt равно role, а не http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role, вы можете установить роль клиентского приложения. утверждение утверждения:

options.TokenValidationParameters = new TokenValidationParameters
{
    RoleClaimType = "role"
};

Другой способ - при добавлении утверждения роли к выданному токену в приложении сервера идентификации используйте ClaimTypes.Role:

new Claim(ClaimTypes.Role, "Admin"),
0 голосов
/ 05 октября 2019

Необходимо сопоставить тип заявки JWT с типом заявки, который использует Identity.

Проблема заключается в том, что система идентификации для ASP.NET Core использует * 1005. * constant (http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role) для определения ролей пользователя. Однако имя заявки, соответствующей роли в маркере JWT OpenID, просто role. Каждый раз, когда вам нужно объединить идентификатор OIDC и ASPИдентификация .NET, вы должны перевести утверждения следующим образом.

Я переписал ваш код немного, потому что вы можете работать с идентификацией утверждений без использования JTokenType. Хотя у меня не было времени, чтобы тщательно протестировать это,если он не привязан к вашему коду, но замените «роль» на ClaimTypes.Role, когда вы добавляете утверждения к идентификатору.

            OpenIdConnectEvents CreateOpenIdConnectEvents()
            {
                return new OpenIdConnectEvents()
                {
                    OnTicketReceived = context =>
                    {
                        var identity = context.Principal.Identity as ClaimsIdentity;
                        if (identity != null)
                        {
                            if (identity.HasClaim(c => c.Type == "role"))
                            {
                                foreach (var role in identity.Claims.Where(c => c.Type == "role"))
                                {
                                    if (!context.Principal.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == role.Value))
                                    {
                                        identity.AddClaim(new Claim(ClaimTypes.Role, role.Value));
                                    }
                                }
                            }

                        }
                        return Task.FromResult(0);
                    }
                };
            }

Используйте так:

options.Events = new CreateOpenIdConnectEvents()
...