Authorization Policies
Authorization is the process of determining what actions an authenticated user is allowed to perform. ASP.NET Core provides a powerful and flexible mechanism for defining and applying authorization rules through policies.
What are Authorization Policies?
Authorization policies are named sets of requirements that must be met for access to be granted. These policies are evaluated by the authorization system, which checks if the current user satisfies all the defined requirements.
Defining Authorization Policies
Authorization policies are typically defined in the application's startup code, specifically in the ConfigureServices
method of the Startup.cs
file. You use the AddAuthorization
extension method on IServiceCollection
to configure the authorization services and add your policies.
A policy is defined by giving it a name and then specifying one or more requirements. The simplest requirement is to check for a specific claim, but policies can also include checks for roles, custom logic, or combinations of these.
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs ConfigureServices method:
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdministratorRole", policy =>
policy.RequireRole("Administrator"));
});
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs ConfigureServices method:
services.AddAuthorization(options =>
{
options.AddPolicy("MustBeEmployee", policy =>
policy.RequireClaim("EmployeeId"));
});
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs ConfigureServices method:
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminAndOnboardingComplete", policy =>
{
policy.RequireRole("Administrator");
policy.RequireClaim("OnboardingComplete", "true");
});
});
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
// In Startup.cs ConfigureServices method:
services.AddAuthorization(options =>
{
options.AddPolicy("RequireSeniorOrManager", policy =>
{
policy.RequireAssertion(context =>
context.User.IsInRole("Senior") || context.User.IsInRole("Manager"));
});
});
Applying Authorization Policies
Once policies are defined, they can be applied to controllers, actions, or Razor Pages using the [Authorize]
attribute.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
[Authorize(Policy = "RequireAdministratorRole")]
public class AdminController : Controller
{
// ... controller actions
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
public class DashboardController : Controller
{
[Authorize(Policy = "MustBeEmployee")]
public IActionResult Index()
{
return View();
}
}
Authorization Handlers
For more complex authorization scenarios, you can create custom authorization handlers. These handlers implement the IAuthorizationHandler
interface and contain custom logic to evaluate requirements.
To use custom handlers, you typically:
- Define a custom requirement class (inherits from
IAuthorizationRequirement
). - Create an authorization handler class (implements
IAuthorizationHandler
). - Register your custom requirement and handler with the authorization system.
using Microsoft.AspNetCore.Authorization;
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using System.Threading.Tasks;
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
{
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(
c => c.Type == ClaimTypes.DateOfBirth).Value);
var ageCalculator = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth.Date > DateTime.Today.AddYears(-ageCalculator))
{
ageCalculator--;
}
if (ageCalculator >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// In Startup.cs ConfigureServices method:
services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();
services.AddAuthorization(options =>
{
options.AddPolicy("MinimumAge18", policy =>
policy.Requirements.Add(new MinimumAgeRequirement(18)));
});
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
public class PartyController : Controller
{
[Authorize(Policy = "MinimumAge18")]
public IActionResult PublicParty()
{
return View();
}
}
RequireAssertion
or chain multiple Require...
calls with an explicit OR condition.
EmployeeId
, DateOfBirth
) are correctly populated during the authentication process.
Conclusion
ASP.NET Core authorization policies offer a robust and declarative way to secure your applications. By defining clear policies, you can effectively manage access control and ensure that only authorized users can perform specific actions, enhancing the security and integrity of your web applications.