In this lesson, you will learn how to create and apply custom attributes to enforce granular access control directly on your controllers and actions.
Moving Beyond Roles with Attributes
While Role-Based Access Control (RBAC) checks if a user is an "Admin," Attribute-Based Access Control (ABAC) asks, "Does this user possess the specific claim required for this resource?" By using custom attributes, we can declaratively secure our code, making authorization logic reusable and highly readable.
Creating a Custom Authorization Attribute
To implement this, we create a class that inherits from AuthorizeAttribute and implements the IAuthorizationFilter interface. This allows us to intercept the request pipeline and inspect the user's claims before the controller action executes.
Here is a simple example of an attribute that checks for a specific department claim:
public class AuthorizeDepartmentAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private readonly string _department;
public AuthorizeDepartmentAttribute(string department)
{
_department = department;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.User;
// Check if the user has the 'Department' claim matching our requirement
if (!user.HasClaim(c => c.Type == "Department" && c.Value == _department))
{
context.Result = new ForbidResult();
}
}
}
Applying the Attribute
Once defined, you can apply this logic to any controller or individual action method. This keeps your business logic clean and separates security concerns from your application flow:
[AuthorizeDepartment("Finance")]
public IActionResult GetFinancialReport()
{
return View();
}
By decorating the method with [AuthorizeDepartment("Finance")], the middleware will automatically trigger the OnAuthorization logic. If the user’s claims do not include a "Department" claim with the value "Finance," they are immediately blocked with a ForbidResult.
This approach is powerful because it allows you to build complex authorization rules—like checking for seniority levels, project access, or security clearances—simply by decorating your code. It turns your authorization requirements into metadata that the framework can process automatically.
Key Takeaway: Custom attributes allow you to encapsulate complex, claim-based authorization rules into reusable decorators that keep your controller logic clean and your access control declarative.