I have an .NET Core 3 WebAPI where I want to use custom policy-based authorization, where one of the policies has multiple requirements.
I have added the policy in Startup.ConfigureServices() and added MyCustomPolicyHandler to DI:
public virtual void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("MyCustomPolicy", policy =>
{
policy.Requirements.Add(new RequirementA());
policy.Requirements.Add(new RequirementB());
policy.Requirements.Add(new RequirementC());
policy.Requirements.Add(new RequirementD());
});
services.AddScoped<IAuthorizationHandler, MyCustomPolicyHandler>();
});
}
I have implemented MyCustomPolicyHandler using the example from this documentation:
Policy-based authorization in ASP.NET Core
public class MyCustomPolicyHandler: IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
var pendingRequirements = context.PendingRequirements.ToList();
Console.WriteLine($"MyCustomPolicyHandler: {pendingRequirements.Count} requirements");
foreach (var requirement in pendingRequirements)
{
if(requirement is RequirementA) {
// do stuff to check the requirements
context.Succeed(requirement);
}
else if(requirement is RequirementB) {
// do stuff to check the requirements
context.Succeed(requirement);
}
else if(requirement is RequirementC) {
// do stuff to check the requirements
context.Succeed(requirement);
}
else if(requirement is RequirementD) {
// do stuff to check the requirements
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
Next, I apply the policy to one of the controller actions:
public class MyController
{
[HttpGet]
[Authorize(Policy="MyCustomPolicy")]
public ActionResult<SomeViewModel> Get(int id) {
// do stuff
return Ok(vm);
}
}
The problem I'm encountering is there are no requirements associated with the policy. The Console.WriteLine() message shows 0 requirements:
MyCustomPolicyHandler: 0 requirements
If I move the policy to the controller, the requirements are present:
[Authorize(Policy="MyCustomPolicy")]
public class MyController
{
[HttpGet]
public ActionResult<SomeViewModel> Get(int id) {
// do stuff
return Ok(vm);
}
}
MyCustomPolicyHandler: 4 requirements
However, I need this policy applied to the action, not the controller. The [Authorize(Policy="MyCustomPolicy")] attribute should work at the action level.
Any idea why this isn't working?
Thanks.
