13

I want to authorize an action controller could access by multiple policies.

.e.g:

[Authorize([Policies.ManageAllCalculationPolicy,Policies.ManageAllPriceListPolicy]]
public async Task<IActionResult> Get(int id){}

Thank a lot.

1
  • IMHO, just add a 3rd policy... Commented Sep 18, 2020 at 3:18

4 Answers 4

23

For multiple policies, you could implement your own AuthorizeAttribute.

  • AuthorizeMultiplePolicyAttribute

     public class AuthorizeMultiplePolicyAttribute:TypeFilterAttribute
     {
     public AuthorizeMultiplePolicyAttribute(string policies,bool IsAll):base(typeof(AuthorizeMultiplePolicyFilter))
     {
         Arguments = new object[] { policies,IsAll};
     }
     }
    
  • AuthorizeMultiplePolicyFilter

     public class AuthorizeMultiplePolicyFilter: IAsyncAuthorizationFilter
     {
     private readonly IAuthorizationService _authorization;
     public string _policies { get; private set; }
     public bool _isAll { get; set; }
     public AuthorizeMultiplePolicyFilter(string policies, bool IsAll,IAuthorizationService authorization)
     {
         _policies = policies;
         _authorization = authorization;
         _isAll = IsAll;
     }
    
     public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
     {
    
         var policys = _policies.Split(";").ToList();
         if (_isAll)
         {
             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;
         }
     }
     }
    
  • Add Policy you want on Startup

     services.AddAuthorization(options =>
         {
    
             options.AddPolicy("ManageAllCalculationPolicy", policy =>
                     policy.RequireAssertion(context =>
                         context.User.HasClaim(c => c.Type == "BadgeId")));
    
             options.AddPolicy("ManageAllPriceListPolicy", policy =>
                     policy.RequireAssertion(context =>
                         context.User.HasClaim(c => c.Type == "aaaa")));
         });
    
  • Authorization based on one of the policies

     [AuthorizeMultiplePolicy("ManageAllCalculationPolicy;ManageAllPriceListPolicy", false)]
    
  • Authorization based on all policies

     [AuthorizeMultiplePolicy("ManageAllCalculationPolicy;ManageAllPriceListPolicy", true)]
    
Sign up to request clarification or add additional context in comments.

4 Comments

I used this with this code ; context.Result = new RedirectToActionResult("Index", "Error", new { code = 403 }); and worked perfectly, thanks for your affords
If you want to use AND you can just use two Authorize attributes. [Authorize("ManageAllCalculationPolicy")] [Authorize("ManageAllPriceListPolicy")]
Visit learn.microsoft.com/en-us/aspnet/core/security/authorization/… Now it's quite simple the answer and it's not necessary to implement more code, Microsoft did it for us.
Again, @Microlang, your link is to an article about role-based authoirzation, not policy-based authorization, which is the subject of this question.
4

No, you cannot add multiple policies as a list with condition or. I think NetCore does not support that.

Try to create a new policy.

services.AddAuthorization(options =>
{
    options.AddPolicy("BadgeEntry", policy =>
        policy.RequireAssertion(context =>
            context.User.HasClaim(c =>
                (c.Type == ClaimTypes.BadgeId ||
                 c.Type == ClaimTypes.TemporaryBadgeId) &&
                 c.Issuer == "https://microsoftsecurity")));
});

Reference: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1#why-would-i-want-multiple-handlers-for-a-requirement

1 Comment

@Microlang No, that link refers to Role-based authorization, not policy-based authorization. You've been able to specify multiple roles in an Authorize attribute for ages.
2

Worked like a charm!!

Here is my part of code in Startup.ConfigureServices

services.AddAuthorization(config =>
                {
                    config.AddPolicy(Policies.Admin, Policies.AdminPolicy());
                    config.AddPolicy(Policies.Register, Policies.RegistradorPolicy());
                });

And, for example.. policies are:

public class Policies
{
        public const string Admin = 'Admin';
        public const string Register = 'Register';

        public static AuthorizationPolicy AdminPolicy()
        {
            return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().RequireRole(Admin).Build();
        }

        public static AuthorizationPolicy RegisterPolicy()
        {
            return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().RequireRole(Register).Build();
        }

}

Then in controllers..

[HttpGet]
        [AuthorizeMultiplePolicy(Policies.Admin + ";" + Policies.Register, false)]
        public ActionResult<IEnumerable<Accion>> GetAll(){
}

Comments

0

You can add multiple policies like that

services.AddAuthorization(options =>
{
    options.AddPolicy("BadgeEntry", PolicyClaimCheck.Any, new string[2] { "VT102","RS102" });
    options.AddPolicy("Notification", PolicyClaimCheck.All, new string[2] { "XTX101","NT102" });
});

If it is enough to have one, you should use PolicyClaimCheck.Any or If it must have all, you should use PolicyClaimCheck.All

1 Comment

Which .NET version is this? PolciyClaimCheck is not available in .net core 3.1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.