Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a custom Authorize attribute for multiple policies in ASP.NET CORE

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.

like image 574
Phong Truong Avatar asked Dec 05 '18 07:12

Phong Truong


People also ask

How do I register a custom authorization filter in .NET Core?

Right-click on the solution and add a new class. Enter the class name and click on Add. Next Inherite Attribute, IAuthorizationFilter to CustomAuthorization class which has overridden the OnAuthorization method. The OnAuthorization Method has the AuthorizationFilterContext parameter.

How does Authorize attribute work in ASP.NET Core?

Authorization in ASP.NET Core is controlled with AuthorizeAttribute and its various parameters. In its most basic form, applying the [Authorize] attribute to a controller, action, or Razor Page, limits access to that component to authenticated users. Now only authenticated users can access the Logout function.

How do I create a custom authorization filter in Web API?

To implement a custom authorization filter, we need to create a class that derives either AuthorizeAttribute , AuthorizationFilterAttribute , or IAuthorizationFilter . AuthorizeAttribute : An action is authorized based on the current user and the user's roles.


2 Answers

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)]
    
like image 169
Xueli Chen Avatar answered Oct 21 '22 12:10

Xueli Chen


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://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1#why-would-i-want-multiple-handlers-for-a-requirement

like image 31
Khai Nguyen Avatar answered Oct 21 '22 10:10

Khai Nguyen