After authentication, identity data is available in HttpContext.User. However, identity is not equal to permission. Permissions should be evaluated by the authorization system.
Authorization in ASP.NET Core
ASP.NET Core provides a policy-based authorization model. Policies can be defined by role, resource, or custom conditions.
Use IAuthorizationService
IAuthorizationService is the core authorization service in ASP.NET Core:
public interface IAuthorizationService
{
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements);
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName);
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, AuthorizationPolicy policy);
}
AuthorizationResult contains success/failure information and reasons.
Implement a custom policy provider
You can use OperationAuthorizationRequirement to model permission requirements and inject them into policies.
public class CustomAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options, IPermissionDefinitionManager permissionDefinitionManager) : DefaultAuthorizationPolicyProvider(options)
Multiple policies are OR-ed; multiple requirements in one policy are AND-ed.
Model authorization resources
public interface IAuthorizationResource
{
string ResourceType => GetType().Name;
string ResourceId => GetType().GetProperty("Id")?.GetValue(this)?.ToString() ?? throw new NotImplementedException();
}
Define a resource record
public record struct ResourceInfo : IAuthorizationResource
Implement authorization handlers
public class PermissionRequirementHandler(IPermissionChecker permissionChecker) : AuthorizationHandler<OperationAuthorizationRequirement>
public class ResourcePermissionRequirementHandler(IPermissionChecker permissionChecker) : AuthorizationHandler<OperationAuthorizationRequirement, IAuthorizationResource>
protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement);
protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, TResource resource);
Use IPermissionChecker in handler
public class PermissionRequirementHandler(IPermissionChecker permissionChecker) : AuthorizationHandler<OperationAuthorizationRequirement>
{
private readonly IPermissionChecker _permissionChecker;
public PermissionRequirementHandler(IPermissionChecker permissionChecker)
{
_permissionChecker = permissionChecker;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement)
{
if (await _permissionChecker.IsGrantedAsync(context.User, requirement.Name))
{
context.Succeed(requirement);
}
}
}