I have an application written with C#
on the top on ASP.NET Core 2.2 framework.
I want to be able to check if a user has a claim before I allow them access to the action.
I created an AuthorizationHandler
to check if the user has the claim like so
public class ClaimExistanceHandler : AuthorizationHandler<MustHaveClaimRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MustHaveClaimRequirement requirement)
{
if (context == null
|| context.User == null
|| context.User.Identity == null
|| !context.User.Identity.IsAuthenticated
|| requirement == null
|| string.IsNullOrWhiteSpace(requirement.Type)
|| context.User.HasClaim(requirement.Type, requirement.Value))
{
context.Fail();
}
else
{
context.Succeed(requirement);
}
await Task.Yield();
}
}
}
then the requirement is as follow
public class MustHaveClaimRequirement : IAuthorizationRequirement
{
public string Type { get; set; }
public string Value { get; set; }
public MustHaveClaimRequirement(string type, string value)
{
Type = type;
Value = value;
}
}
But how can I call this requirement as an attribute? For example HasPermission("do something", "1")
It seems that my HasPermission class needs to implement the AuthorizeAttribute
but not sure how would I call the handler from the attribute.
Your primary goal here is to get the requirement into a policy, and then use or create an attribute that can specify that policy with a string name. Once you do that, don't need to worry about calling the handler yourself, because ASP.NET Core will take care of that for you.
The simplest method of creating policies is to do it on app startup, as documented here. You create your policies, then use AuthorizeAttribute
to specify which policy to attach to each endpoint.
However, doing it this way requires you to define all your policies up front. If that would result in you needing to create tons of different policies (because you are going to be checking lots of different claim types), and what you really want is to be able to have an attribute that specifies the claim information, there is a more dynamic way of doing it: see here. You need to create an AuthorizeAttribute
implementation that stuffs your parameter values (name and type) into a string, and create and register an IAuthorizationPolicyProvider
that can interpret that string and generate a policy with the appropriate requirement.
EDIT: It's also worth pointing out that ASP.NET Core already includes a requirement implementation for checking a claim: ClaimsAuthorizationRequirement
. AuthorizationPolicyBuilder
has a shortcut for it (RequireClaim
) so you can quickly create policies that check claims:
services.AddAuthorization(options =>
{
options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With