How to create a custom AuthorizeAttribute in ASP.NET Core
By FoxLearn 11/12/2024 2:39:31 AM 121
The ASP.NET Core team recommends using the policy-based authorization approach instead of the older AuthorizeCore
method, which has been deprecated. The new approach is based on defining authorization policies and applying them with the [Authorize]
attribute.
The introduction of policy-based authorization in ASP.NET Core is a powerful feature, but it's not always the best fit for every scenario, especially when dealing with scenarios that require fine-grained control over permissions, such as when each action or controller requires a specific claim, like "CanCreateOrder," "CanReadOrder," etc.
In such scenarios, using the IAuthorizationFilter
interface provides a lightweight and effective way to enforce claim-based requirements on controllers or actions.
This approach bypasses the complexity of defining policies and handlers, and allows you to check for specific claims directly, offering a more concise and flexible solution for many common authorization needs.
public class ClaimRequirementAttribute : TypeFilterAttribute { public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter)) { Arguments = new object[] {new Claim(claimType, claimValue) }; } } public class ClaimRequirementFilter : IAuthorizationFilter { readonly Claim _claim; public ClaimRequirementFilter(Claim claim) { _claim = claim; } public void OnAuthorization(AuthorizationFilterContext context) { var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value); if (!hasClaim) { context.Result = new ForbidResult(); } } }
Usage
[Route("api/resource")] public class MyController : Controller { [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")] [HttpGet] public IActionResult GetResource() { return Ok(); } }
In ASP.NET Core 2, the framework reintroduced the ability to inherit from AuthorizeAttribute
, but with a key change: you now need to implement either IAuthorizationFilter
or IAsyncAuthorizationFilter
for custom authorization logic.
For example:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter { private readonly string _someFilterParameter; public CustomAuthorizeAttribute(string someFilterParameter) { _someFilterParameter = someFilterParameter; } public void OnAuthorization(AuthorizationFilterContext context) { var user = context.HttpContext.User; if (!user.Identity.IsAuthenticated) { // it isn't needed to set unauthorized result // as the base class already requires the user to be authenticated // this also makes redirect to a login page work properly // context.Result = new UnauthorizedResult(); return; } // you can also use registered services var someService = context.HttpContext.RequestServices.GetService<ISomeService>(); var isAuthorized = someService.IsUserAuthorized(user.Identity.Name, _someFilterParameter); if (!isAuthorized) { context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.Forbidden); return; } } }
- How to enable CORS in ASP.NET Core WebAPI
- How to fix 'DbContextOptionsBuilder' does not contain a definition for 'UseSqlServer'
- Unable to resolve service for type 'Microsoft.AspNetCore.Identity.RoleManager'
- HTTP Error 500.30 ASP.NET Core app failed to start
- How to Use IExceptionHandler in ASP.NET Core
- How to custom exception handling in ASP.NET Core
- How to manually resolve a type using the ASP.NET Core MVC
- Differences Between AddTransient, AddScoped, and AddSingleton