Same Policy but different required parameter for each action method

140 views Asked by At

In a .Net core Webapi 2.1 project, I have a tons of action methods.
All action methods should be authorized against the same policy (named FooPolicy) but with a different required argument.
Based on Microsoft's docs: Policy-based-Authorization One way would be to declare a tons of policies based on different input argument:

services.AddAuthorization(options =>
{
    options.AddPolicy("FooPolicy1", policy =>policy.Requirements.Add(new FooRequirement(1)));
    options.AddPolicy("FooPolicy2", policy =>policy.Requirements.Add(new FooRequirement(2)));
    options.AddPolicy("FooPolicy3", policy =>policy.Requirements.Add(new FooRequirement(3)));
    //... May be 30 more same policies here ...
});

As i earlier mentioned, only different part is in new FooRequirement(diffArgs). The other challenge for this solution would be to add each FooPolicy on it's corresponding action method and you may miss a couple of theme:

[Authorize(Policy = "FooPolicy1")]
public IActionResult ActionMethodFoo1(...) {...}

[Authorize(Policy = "FooPolicy2")]
public IActionResult ActionMethodFoo2(...) {...}

[Authorize(Policy = "FooPolicy3")]
public IActionResult ActionMethodFoo3(...) {...}
...List still goes on...

Is there any solution like: declare a policy once but use it with different instance of FooRequirement (which is of type IAuthorizationHandler)? like so:

services.AddAuthorization(options =>
{
    options.AddPolicy("FooPolicy", policy =>policy.Requirements.Add(?));
});

And on the action methods:

[Authorize(Policy = "FooPolicy", required = new FooRequirement(1))]
public IActionResult ActionMethodFoo1(...) {...}

[Authorize(Policy = "FooPolicy", required = new FooRequirement(2))]
public IActionResult ActionMethodFoo2(...) {...}

[Authorize(Policy = "FooPolicy", required = new FooRequirement(3))]
public IActionResult ActionMethodFoo3(...) {...}

The main idea is to declare policy once. Two recent code blocks are psudo-code, Does any body knows practical solution with similar concept?

1

There are 1 answers

0
Edward On BEST ANSWER

You could implement your own IAuthorizationFilter

  1. custom IAuthorizationFilter

    public class CustomAuthorize : IAuthorizationFilter         
     {
            private readonly int _input;
    
    public CustomAuthorize(int input)
    {
        _input = input;
    }
    
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //custom validation rule
        if (_input == 1)
        {
            context.Result = new ForbidResult();
        }
    }
    }
    
  2. Custom CustomAuthorizeAttribute

    public class CustomAuthorizeAttribute : TypeFilterAttribute
    {
    public CustomAuthorizeAttribute(int input) : base(typeof(CustomAuthorize))
    {
        Arguments = new object[] { input };
    }
    }
    
  3. Use

    [CustomAuthorizeAttribute(1)]
    public IActionResult About()