Reputation: 342
I've always used role authorization in my .net application. However, I'm building a demo app and want to give claims a try. I've always decorated my controller like this where either an admin or User with full access can be authorized.
[[Authorize(Roles = "IsApiUserFullAccess", "IsAdmin") ]]
However, I can't accomplish the same with claims. In my startup, I have these two claims policies. How can I decorate my controller or change these policies to make either claims to be authorize by my controller?
options.AddPolicy("IsApiUserFullAccess", policy => policy.RequireClaim("apiuser.fullaccess", "true"));
options.AddPolicy("IsAdmin", policy => policy.RequireClaim("administrator", "true"));
Upvotes: 7
Views: 2381
Reputation: 1778
You can use the RequireAssertion() method which accepts a Func<> to fullfill a policy.
Example:
services.AddAuthorization(options =>
{
options.AddPolicy("AdminOrFullAccess", policy =>
policy.RequireAssertion(context =>
{
bool isApiUserFullAccess = context.User.HasClaim(c => ...);
bool isAdmin = context.User.IsInRole("ADMIN_ROLE");
return isAdmin || isApiUserFullAccess;
});
});
Upvotes: 11
Reputation: 13940
One way would be to build a custom policy with a requirement and handler that ORs the user's claims, like so:
// Marker class
public class HasFullAccessOrAdminRequirement : IAuthorizationRequirement {}
public class HasFullAccessOrAdminHandler
: AuthorizationHandler<HasFullAccessOrAdminRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
HasFullAccessOrAdminRequirement requirement)
{
var user = context.User;
if (user.HasClaim(...) || user.HasClaim(...))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Then register it:
options.AddPolicy("AdminOrFullAccess", builder =>
builder.AddRequirements(new HasFullAccessOrAdminRequirement());
Then use it: [Authorize("AdminOrFullAccess")]
Upvotes: 4