---
title: Custom Policy-Based Authorization | Microsoft Docs
author: rick-anderson
description:
keywords: ASP.NET Core,
ms.author: riande
manager: wpickett
ms.date: 10/14/2016
ms.topic: article
ms.assetid: e422a1b2-dc4a-4bcc-b8d9-7ee62009b6a3
ms.technology: aspnet
ms.prod: asp.net-core
uid: security/authorization/policies
---
# Custom Policy-Based Authorization
Underneath the covers the [role authorization](roles.md#security-authorization-role-based) and [claims authorization](claims.md#security-authorization-claims-based) make use of a requirement, a handler for the requirement and a pre-configured policy. These building blocks allow you to express authorization evaluations in code, allowing for a richer, reusable, and easily testable authorization structure.
An authorization policy is made up of one or more requirements and registered at application startup as part of the Authorization service configuration, in `ConfigureServices` in the *Startup.cs* file.
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
}
```
Here you can see an "Over21" policy is created with a single requirement, that of a minimum age, which is passed as a parameter to the requirement.
Policies are applied using the `Authorize` attribute by specifying the policy name, for example;
```csharp
[Authorize(Policy="Over21")]
public class AlcoholPurchaseRequirementsController : Controller
{
public ActionResult Login()
{
}
public ActionResult Logout()
{
}
}
```
## Requirements
An authorization requirement is a collection of data parameters that a policy can use to evaluate the current user principal. In our Minimum Age policy the requirement we have is a single parameter, the minimum age. A requirement must implement `IAuthorizationRequirement`. This is an empty, marker interface. A parameterized minimum age requirement might be implemented as follows;
```csharp
public class MinimumAgeRequirement : IAuthorizationRequirement
{
public int MinimumAge { get; private set; }
public MinimumAgeRequirement(int minimumAge)
{
MinimumAge = minimumAge;
}
}
```
A requirement doesn't need to have data or properties.
## Authorization Handlers
An authorization handler is responsible for the evaluation of any properties of a requirement. The authorization handler must evaluate them against a provided `AuthorizationHandlerContext` to decide if authorization is allowed. A requirement can have [multiple handlers](policies.md#security-authorization-policies-based-multiple-handlers). Handlers must inherit `AuthorizationHandler` where T is the requirement it handles.
The minimum age handler might look like this:
```csharp
public class MinimumAgeHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
c.Issuer == "http://contoso.com"))
{
// .NET 4.x -> return Task.FromResult(0);
return Task.CompletedTask;
}
var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(
c => c.Type == ClaimTypes.DateOfBirth && c.Issuer == "http://contoso.com").Value);
int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
{
calculatedAge--;
}
if (calculatedAge >= requirement.MinimumAge)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
```
In the code above we first look to see if the current user principal has a date of birth claim which has been issued by an Issuer we know and trust. If the claim is missing we can't authorize so we return. If we have a claim, we figure out how old the user is, and if they meet the minimum age passed in by the requirement then authorization has been successful. Once authorization is successful we call `context.Succeed()` passing in the requirement that has been successful as a parameter.
Handlers must be registered in the services collection during configuration, for example;
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization(options =>
{
options.AddPolicy("Over21",
policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
});
services.AddSingleton();
}
```
Each handler is added to the services collection by using `services.AddSingleton();` passing in your handler class.
## What should a handler return?
You can see in our [handler example](policies.md#security-authorization-handler-example) that the `Handle()` method has no return value, so how do we indicate success or failure?
* A handler indicates success by calling `context.Succeed(IAuthorizationRequirement requirement)`, passing the requirement that has been successfully validated.
* A handler does not need to handle failures generally, as other handlers for the same requirement may succeed.
* To guarantee failure even if other handlers for a requirement succeed, call `context.Fail`.
Regardless of what you call inside your handler all handlers for a requirement will be called when a policy requires the requirement. This allows requirements to have side effects, such as logging, which will always take place even if `context.Fail()` has been called in another handler.
## Why would I want multiple handlers for a requirement?
In cases where you want evaluation to be on an **OR** basis you implement multiple handlers for a single requirement. For example, Microsoft has doors which only open with key cards. If you leave your key card at home the receptionist prints a temporary sticker and opens the door for you. In this scenario you'd have a single requirement, *EnterBuilding*, but multiple handlers, each one examining a single requirement.
```csharp
public class EnterBuildingRequirement : IAuthorizationRequirement
{
}
public class BadgeEntryHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EnterBuildingRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == ClaimTypes.BadgeId &&
c.Issuer == "http://microsoftsecurity"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class HasTemporaryStickerHandler : AuthorizationHandler
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EnterBuildingRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == ClaimTypes.TemporaryBadgeId &&
c.Issuer == "https://microsoftsecurity"))
{
// We'd also check the expiration date on the sticker.
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
```
Now, assuming both handlers are [registered](xref:security/authorization/policies#security-authorization-policies-based-handler-registration) when a policy evaluates the `EnterBuildingRequirement` if either handler succeeds the policy evaluation will succeed.
## Using a func to fufill a policy
There may be occasions where fufilling a policy is simple to express in code. It is possible to simply supply a `Func` when configuring your policy with the `RequireAssertion` policy builder.
For example the previous `BadgeEntryHandler` could be rewritten as follows;
```csharp
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry",
policy => policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == ClaimTypes.BadgeId ||
c.Type == ClaimTypes.TemporaryBadgeId)
&& c.Issuer == "https://microsoftsecurity"));
}));
}
}
```
## Accessing MVC Request Context In Handlers
The `Handle` method you must implement in an authorization handler has two parameters, an `AuthorizationContext` and the `Requirement` you are handling. Frameworks such as MVC or Jabbr are free to add any object to the `Resource` property on the `AuthorizationContext` to pass through extra information.
For example MVC passes an instance of `Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext` in the resource property which is used to access HttpContext, RouteData and everything else MVC provides.
The use of the `Resource` property is framework specific. Using information in the `Resource` property will limit your authorization policies to particular frameworks. You should cast the `Resource` property using the `as` keyword, and then check the cast has succeed to ensure your code doesn't crash with `InvalidCastExceptions` when run on other frameworks;
```csharp
if (context.Resource is Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext mvcContext)
{
// Examine MVC specific things like routing data.
}
```