How to add multiple policies in action using Authorize attribute using identity 2.0?
If you simply want to apply multiple policies, you can do this:
[Authorize(Policy = "Asset")]
[Authorize(Policy = "Edit")]
public class MyController : Controller {
}
EDIT: to clarify, this is additive - you must pass both policy requirements.
For multiple policys, you could implement your own AuthorizeAttribute
.
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; } } }
only require one of the policy
[MultiplePolicysAuthorize("Assets View;Assets Edit;Assets Delete")]
only require all the policys
[MultiplePolicysAuthorize("Assets View;Assets Edit;Assets Delete", true)]
You can use make multiple requirements class implementing IAuthorizationRequirement
, and register to the DI container the multiple requirements handlers of AuthorizationHandler
.
So you can simply add them to your Policy using the AddRequirement
inside AuthorizationPolicyBuilder
public AuthorizationPolicyBuilder AddRequirements(params IAuthorizationRequirement[] requirements);
Startup.cs:
services.AddScoped<IAuthorizationHandler, FooHandler>();
services.AddScoped<IAuthorizationHandler, BooHandler>();
services.AddAuthorization(authorizationOptions =>
{
authorizationOptions.AddPolicy(
"FooAndBooPolicy",
policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser();
policyBuilder.AddRequirements(new FooRequirement(), new BooRequirement());
});
});
Requirements.cs:
public class FooRequirement : IAuthorizationRequirement { }
public class FooHandler : AuthorizationHandler<FooRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationContext context, FooRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "Foo" && c.Value == true))
{
context.Succeed(requirement);
return Task.FromResult(0);
}
}
}
public class BooRequirement : IAuthorizationRequirement { }
public class BooHandler : AuthorizationHandler<BooRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationContext context, BooRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "Boo" && c.Value == true))
{
context.Succeed(requirement);
return Task.FromResult(0);
}
}
}