Section 6 of 6
Custom Authorization Handlers
🎯 What You'll Learn
- Creating custom requirements
- Creating custom handlers
- Dependency injection in handlers
- Multiple handlers
- Complete examples
Creating Custom Requirements
Custom requirements allow you to implement complex authorization logic beyond roles and claims.
MinimumAgeRequirement.cs
C#
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
Creating Custom Handlers
MinimumAgeHandler.cs
C#
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
var birthDateClaim = context.User.FindFirst("BirthDate");
if (birthDateClaim == null)
return Task.CompletedTask;
if (DateTime.TryParse(birthDateClaim.Value, out var birthDate))
{
var age = DateTime.Today.Year - birthDate.Year;
if (age >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
Dependency Injection in Handlers
Handler with DbContext
C#
public class ActiveSubscriptionHandler
: AuthorizationHandler<ActiveSubscriptionRequirement>
{
private readonly InvenTrackDbContext _context;
public ActiveSubscriptionHandler(InvenTrackDbContext context)
{
_context = context;
}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ActiveSubscriptionRequirement requirement)
{
var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var hasActiveSubscription = await _context.Subscriptions
.AnyAsync(s => s.UserId == userId && s.IsActive);
if (hasActiveSubscription)
{
context.Succeed(requirement);
}
}
}
Registering Handlers
Program.cs
C#
// Register handlers
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
builder.Services.AddScoped<IAuthorizationHandler, ActiveSubscriptionHandler>();
// Create policies
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Over18", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(18)));
options.AddPolicy("ActiveSubscription", policy =>
policy.Requirements.Add(new ActiveSubscriptionRequirement()));
});
Complete InvenTrack Example
BusinessHoursRequirement.cs
C#
public class BusinessHoursRequirement : IAuthorizationRequirement
{
}
BusinessHoursHandler.cs
C#
public class BusinessHoursHandler : AuthorizationHandler<BusinessHoursRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
BusinessHoursRequirement requirement)
{
var currentHour = DateTime.Now.Hour;
// Business hours: 9 AM - 5 PM
if (currentHour >= 9 && currentHour < 17)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// Usage in Program.cs
builder.Services.AddSingleton<IAuthorizationHandler, BusinessHoursHandler>();
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("BusinessHoursOnly", policy =>
policy.Requirements.Add(new BusinessHoursRequirement()));
});
// Usage in Controller
[Authorize(Policy = "BusinessHoursOnly")]
public IActionResult CreateOrder()
{
return View();
}
Key Takeaways
- IAuthorizationRequirement: Define custom requirement
- AuthorizationHandler: Implement authorization logic
- context.Succeed(): Mark requirement as satisfied
- Dependency injection: Inject services into handlers
- Singleton vs Scoped: Choose based on dependencies
- Flexible: Implement any authorization logic
🎉 Part XIII Complete!
Congratulations! You've completed Part XIII: Authorization. You now understand:
- ✅ Authorization fundamentals ([Authorize], UseAuthorization)
- ✅ Role-based authorization (roles, [Authorize(Roles)])
- ✅ Claims-based authorization (claims, RequireClaim)
- ✅ Policy-based authorization (policies, combining requirements)
- ✅ Resource-based authorization (IAuthorizationService, AuthorizeAsync)
- ✅ Custom authorization handlers (IAuthorizationRequirement, AuthorizationHandler)
You now have the skills to implement comprehensive authorization in your ASP.NET Core applications! 🚀