IdentityServer: несколько клиентов с разными типами грантов, политики не работают должным образом - PullRequest
0 голосов
/ 04 марта 2020

У меня есть настройка сервера идентификации со следующей конфигурацией «похож на»:

        return new List<Client>
        {
            new Client
            {
                [...]
                AllowedGrantTypes = GrantTypes.Implicit,
                [....]
            },
            new Client
            {
                [...]
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                [....]
            }
        };

и аннотациями, помеченными так:

    [Route("api/forms")]
    [ApiController]
    [Authorize(Policy = "user.api.portfolio.manager")]
    [Authorize(Policy = "application.api.portfolio.manager")]
   public class FormsController : ControllerBase
   {
      [...]
   }

и политикой

        private System.Action<AuthorizationOptions> AddJwtAuthorizationPolicyForRole()
        {
            return options => { options.AddPolicy("**POLICY_FOR_GRANT_IMPLICIT**", policy => { 
                policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); 
                policy.RequireAuthenticatedUser();
                policy.RequireClaim(ClaimTypes.Role, "USER_ACCESSIBLE");
            }); 
            };
        }

        private System.Action<AuthorizationOptions> AddJwtAuthorizationPolicyForRole()
        {
            return options => { options.AddPolicy("**POLICY_FOR_CLIENT_CREDENTIALS**", policy => { 
                policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); 
                policy.RequireAuthenticatedUser();
            }); 
            };
        }

, поэтому я хочу достичь:

Клиенты, использующие GrantType.ClientCredentials, могут обращаться к контроллеру без каких-либо дополнительных потребностей. Клиенты, использующие неявную схему, должны иметь роль USER_ACCESSIBLE

Если она настроена так, как показано выше, обе политики должны применяться -> Оба типа предоставления не работают.

Как мне добиться описанного поведения с помощью IdentityServer, что у каждого типа гранта может быть независимая политика, которую следует применять?

Заранее благодарим за помощь.

1 Ответ

1 голос
/ 05 марта 2020

Наиболее простым решением является добавление еще одной единой политики для Implicit + ClientCredential для реализации логики для условий OR.

Или вы можете создать собственный атрибут, например:

  • MultiplePolicysAuthorizeAttribute

    public class MultiplePolicysAuthorizeAttribute : TypeFilterAttribute
    {
         public MultiplePolicysAuthorizeAttribute(string policys, bool isAnd = false) : base(typeof(MultiplePolicysAuthorizeFilter))
         {
             Arguments = new object[] { policys, isAnd };
         }
    }
    
  • MultiplePolicysAuthorizeFilter

    public class MultiplePolicysAuthorizeFilter : IAsyncAuthorizationFilter
    {
        private readonly IAuthorizationService _authorization;
        public string Policys { get; private set; }
        public bool IsAnd { get; private set; }
    
        public MultiplePolicysAuthorizeFilter(string policys, bool isAnd, IAuthorizationService authorization)
        {
           Policys = policys;
           IsAnd = isAnd;
           _authorization = authorization;
        }
    
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var policys = Policys.Split(";").ToList();
            if (IsAnd)
            {
                foreach (var policy in policys)
                {
                    var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
                    if (!authorized.Succeeded)
                    {
                        context.Result = new ForbidResult();
                        return;
                    }
    
                }
             }
             else
             {
                foreach (var policy in policys)
                {
                     var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
                     if (authorized.Succeeded)
                     {
                         return;
                     }
    
                }
                context.Result = new ForbidResult();
                return;
            }
         }
    }
    

Если действия требуют соответствия одной из политик (ИЛИ):

[MultiplePolicysAuthorize("POLICY_FOR_GRANT_IMPLICIT;POLICY_FOR_CLIENT_CREDENTIALS")]

Если действия требуют соответствия всем политикам (А):

[MultiplePolicysAuthorize("POLICY_FOR_GRANT_IMPLICIT;POLICY_FOR_CLIENT_CREDENTIALS",true)]

Пример кода: { ссылка }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...