{"id":82839,"date":"2019-01-08T16:29:26","date_gmt":"2019-01-08T16:29:26","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=82839"},"modified":"2026-04-15T18:08:42","modified_gmt":"2026-04-15T18:08:42","slug":"policy-based-authorization-in-asp-net-core-a-deep-dive","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/policy-based-authorization-in-asp-net-core-a-deep-dive\/","title":{"rendered":"ASP.NET Core Policy-Based Authorization: Requirements, Handlers, and Claims"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\" id=\"h-executive-summary\">Executive Summary<\/h2>\n\n\n\n<p><strong>ASP.NET Core policy-based authorization replaces the simple [Authorize(Roles = &#8220;Admin&#8221;)] attribute with a flexible, declarative model built from three objects: requirements (what conditions must be met), handlers (the code that evaluates those conditions), and policies (named combinations of requirements registered with the middleware). This allows complex, reusable authorization rules &#8211; such as &#8216;user must be over 18 and in the Premium tier&#8217; &#8211; to be expressed cleanly and applied across controllers and actions. This article covers the full hierarchy: role-based authorization (the baseline), claims-based authorization via policies, custom requirements, authorization handlers, multiple handlers for a single requirement, and policy registration.<\/strong><\/p>\n\n\n\n<p><em>Take advantage of Policy-based authorization, a simple, rich, expressive and reusable authorization model, to secure your applications written in ASP.NET Core<\/em><\/p>\n\n\n\n<p>Authentication and Authorization are two terms you would often come across when reading about the security of web applications. While the former is used to validate a user&#8217;s credentials, the latter is used to grant access to one or more resources of the application to a user. There are two ways in which you can implement authorization in ASP.NET Core. These include role-based authorization and policy-based authorization. Role-based authorization has been in use from the previous versions of ASP.NET. Policy-based authorization has been newly introduced in ASP.NET Core and provides a rich, expressive and reusable authorization model to secure applications developed in ASP.NET Core. This article presents a discussion on how you can work with policy-based authorization in ASP.NET Core.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-prerequisites\">Prerequisites<\/h2>\n\n\n\n<p>To work with the code examples provided in this article, you should have Visual Studio 2017 and NET. Core installed in your system. If you don\u2019t have .NET Core installed in your system, you can download a copy from <a href=\"https:\/\/dotnet.microsoft.com\/download\/archives\">here<\/a>. You can download Visual Studio 2017 from this <a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">link<\/a>.<\/p>\n\n\n\n<p>Before the deep dive into how the policy-based authorization model works, here\u2019s a quick tour of the role-based security model to understand the constraints of the role-based security model and then learn why the policy-based authorization model should be used.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-role-based-authorization-in-asp-net-core\">Role-based Authorization in ASP.NET Core<\/h2>\n\n\n\n<p>A <em>role<\/em> is a string value that is mapped to a set of permissions for an authenticated user. The role-based security model has been in use from the days of ASP.NET. Role-based authorization is a declarative way to restrict access to resources. You can specify the roles that the current user must be a member of to access a specified resource. The <code>Authorize<\/code> attribute enables you to restrict access to resources based on roles. It is a declarative attribute that can be applied to a controller or an action method. If you specify this attribute without any arguments, it only checks if the user is authenticated. Here\u2019s an example that illustrates how this attribute can be applied to a controller.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n[Authorize]\npublic class UserController : Controller\n{\n  \/\/Action methods\n}<\/pre>\n\n\n\n<p>The following code snippet can be used to limit access to the <code>SecurityController<\/code> to only those users who are administrators, i.e., those users who are a member of the <em>Administrator<\/em> role.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Roles = \"Administrator\")]\npublic class SecurityController : Controller\n{\n  \/\/Usual code\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-multiple-roles\">Multiple Roles<\/h2>\n\n\n\n<p>You can also specify multiple roles, separated by a comma. Here&#8217;s an example that illustrates this.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Roles = \"Manager,Administrator\")]\npublic class DocumentsController : Controller\n{\n   \/\/Action methods\n}<\/pre>\n\n\n\n<p>In this example, only those users who pertain to the <em>Manager<\/em> or <em>Administrator<\/em> role can have access to the <code>DocumentsController<\/code> and all its methods.<\/p>\n\n\n\n<p>Note that you can apply roles both at the controller and the action levels. As an example, even if users having either <em>Manager<\/em> or <em>Administrator<\/em> roles can access the <code>DocumentsController<\/code> and its methods, you may want a method of this controller class to be accessed only by users who belong to the <em>Administrator<\/em> role. The following code snippet shows how this can be achieved.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Roles = \"Manager, Administrator\")]\npublic class DocumentsController : Controller\n{\n    public ActionResult ViewDocument()\n    {\n        \/\/Your code here\n    }\n    [Authorize(Roles = \"Administrator\")]\n    public ActionResult DeleteAllDocuments()\n    {\n        \/\/Your code here\n    }\n}<\/pre>\n\n\n\n<p>Now, suppose you would want users who belong to both <em>Manager<\/em> and <em>Administrator<\/em> roles should only have access to the <code>DocumentsController<\/code> and its methods. The following code snippet shows how you can define roles in such a way that the users who access the <code>DocumentsController<\/code> and its methods must be a member of both <em>Manager<\/em> and <em>Administrator<\/em> roles.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Roles = \"Manager\")]\n[Authorize(Roles = \"Administrator\")]\npublic class DocumentsController  : Controller\n{\n}<\/pre>\n\n\n\n<p>Albeit its ease of use, role-based <a id=\"post-82839-_Hlk534373138\"><\/a>authorization has its limitations. This is exactly why policy-based authorization is used. In the sections that follow you will examine how you can work with policy-based authorization in ASP.NET Core.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-need-for-policy-based-authorization\">The Need for Policy-based Authorization<\/h2>\n\n\n\n<p>Authorization and access control using roles for protecting resources from unauthorized access have been in use for quite some time. However, they aren&#8217;t very expressive, and you may run into problems when the number of roles that are needed is significantly high.<\/p>\n\n\n\n<p>Here\u2019s a scenario with an example to explain. Suppose you are tasked with designing a security framework for an application. Initially, there are three roles in an application, i.e., <em>User<\/em>, <em>Admin,<\/em> and <em>Manager<\/em>. Now if you have multiple variations of the <em>Admin<\/em> role, like, <em>CustomerAdmin<\/em>, <em>ReportsAdmin<\/em>, and <em>SuperAdmin<\/em>, you would have to consider each of these when you are designing the security framework. You can also have multiple variations of the <em>Manager<\/em> role &#8211; your framework will have to consider these as well. As the number of these roles increases significantly, it becomes extremely difficult to effectively handle the roles. Here&#8217;s exactly where a policy-based authorization model comes in.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-working-with-policy-based-authorization-in-asp-net-core\">Working with Policy-based Authorization in ASP.NET Core<\/h2>\n\n\n\n<p>A policy-based security model decouples authorization and application logic and provides a flexible, reusable and extensible security model in ASP.NET Core. The policy-based security model is centered on three main concepts. These include policies, requirements, and handlers. A policy is comprised of several requirements. A requirement, in turn, contains data parameters to validate the user\u2019s identity. Lastly, a handler is used to determine if a user has access to a specific resource. We\u2019ll discuss each of these in more detail in this section \u2013 we\u2019ll start with a policy.<\/p>\n\n\n\n<p>Essentially, a policy is comprised of one or more requirements and is usually registered at application startup in the <code>ConfigureServices()<\/code> method of the <em>Startup.cs<\/em> file. To apply the policies in your controllers or action methods, you can take advantage of the <code>AuthorizeAttribute<\/code> attribute or the <code>AuthorizeFilter<\/code> filter.<\/p>\n\n\n\n<p>You can create a policy instance using the <code>AuthorizationPolicyBuilder<\/code> class as shown in the code snippet given below. You can specify the role names using the <code>RequireRole<\/code> method.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var policy = new AuthorizationPolicyBuilder()\n  .RequireAuthenticatedUser()\n  .RequireRole(\"Admin\")\n  .Build();<\/pre>\n\n\n\n<p>Alternatively, you can create the policy instance in the <code>ConfigureServices<\/code> method as shown in the code snippet given below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> services.AddMvc(obj =&gt;\n            {\n                var policy = new AuthorizationPolicyBuilder()\n                    .RequireAuthenticatedUser()\n                    .Build();\n                obj.Filters.Add(new AuthorizeFilter(policy));\n            });<\/pre>\n\n\n\n<p>You\u2019ll see more on this in the sections that follow.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-registering-a-policy\">Registering a Policy<\/h2>\n\n\n\n<p>Merely defining the policies isn\u2019t enough \u2013 you should also register the policies you\u2019ve defined with the authorization middleware. To register a policy, you should specify a name \u2013 this name would be used to reference the policy in the controller or the action methods.<\/p>\n\n\n\n<p>The following code snippet illustrates how a policy can be registered at application startup in ASP.NET Core.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">using Microsoft.Extensions.DependencyInjection;\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddAuthorization(options =&gt;\n    {\n        options.AddPolicy(\"RequireManagerOnly\", policy =&gt; \n               policy.RequireRole(\"Manager\"));\n    });\n}<\/pre>\n\n\n\n<p>You can also specify multiple allowed roles when registering the policy as shown in the code snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">    services.AddAuthorization(options =&gt;\n    {\n        options.AddPolicy(\"RequireManagerOnly\", policy =&gt; \n              policy.RequireRole(\"Manager\",\"Administrator\"));\n    });<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-applying-the-policy\">Applying the Policy<\/h2>\n\n\n\n<p>Once the policy has been registered, you can apply the policy in your controller or the controller&#8217;s action methods. If you were to apply the policy at the controller level, here\u2019s how you would need to specify the policy.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Policy = \"RequireAdminOnly\")]\npublic class SecurityController: Controller\n{\n    \/\/Action methods\n}<\/pre>\n\n\n\n<p>As you can see, instead of specifying roles in the <code>[Authorize]<\/code> attribute, you can specify the policy that you would like to apply. To apply a policy to an action method, you can take advantage of the <code>Policy<\/code> property of the <code>Authorize<\/code> attribute as shown in the code snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Policy = \"RequireAdminOnly\")]\npublic IActionResult DeleteAllSecureDocuments()\n{\n    \/\/Some code\n}<\/pre>\n\n\n\n<p>You can also apply multiple policies to a controller or an action method. The following code snippet illustrates how this can be achieved.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Policy = \"ShouldBeEmployeeOnly\")]\npublic class SecurityController : Controller\n{\n    [Authorize(Policy = \"RequireAdminOnly\")]\n    public ActionResult DeleteUser()\n    {\n        \/\/Your code here\n    }\n}<\/pre>\n\n\n\n<p>In the above code example, you can see two policies applied &#8211; one at the controller level and the other at the action level. Refer to the <code>DeleteUser<\/code> action method in the code example above. This action method can be executed only by users who satisfy both the policies, namely <em>ShouldBeEmployeeOnly<\/em> and <em>Administrator<\/em>. In other words, to call the <code>DeleteUser<\/code> method, the identity must fulfill the two policies <em>ShouldBeEmployeeOnly<\/em> and <em>Administrator<\/em>.<\/p>\n\n\n\n<p>Although role-based authorization is easy to implement in ASP.NET Core, it has limited scope. As an example, imagine that you need to validate a user based on the <em>Joining date<\/em> or <em>Department Id<\/em>. You cannot have roles for each of such variations &#8211; that&#8217;s not a good solution at all. Here&#8217;s where you can take advantage of claims-based authorization &#8211; you can validate the identity of a user based on the claims. The section that follows examines how you can work with claims-based authorization via policies.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-using-claims-based-authorization-via-policies\">Using Claims Based Authorization via Policies<\/h2>\n\n\n\n<p>Claims based authorization provides a declarative way of checking access to resources. In this type of authorization, you would typically check the value of a claim and then grant access to a resource based on the value contained in the claim. First off, understand what a claim is. A claim is a key-value pair that represents a subject, i.e., <em>name<\/em>, <em>age<\/em>, <em>passportnumber<\/em>, <em>drivinglicense<\/em>, <em>passport<\/em>, <em>nationality<\/em>, <em>dateofbirth<\/em>, etc. So, if <em>dateofbirth<\/em> is the claim name, the claim value would be the date of birth, i.e., <em>1<sup>st<\/sup> January 1970<\/em>.<\/p>\n\n\n\n<p>It should be noted that a claim is given to a trusted party only. As mentioned above, a claim represents the subject \u2013 tells you who the subject is. However, a claim has nothing to do with what the subject can do \u2013 it never tells you that.<\/p>\n\n\n\n<p>Claims based authorization can be implemented using policies. In this section, you will explore how you can work with policy-based claims. The code snippet given below shows how a simple claim policy is registered. The <em>ShouldBeOnlyEmployee<\/em> policy looks for the presence of the <em>EmployeeId<\/em> claim. The policy is added to the services collection using the <code>AddPolicy<\/code> method.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddAuthorization(options =&gt;\n    {\n        options.AddPolicy(\"ShouldBeOnlyEmployee\", policy =&gt; \n              policy.RequireClaim(\"EmployeeId\"));\n    });\n}<\/pre>\n\n\n\n<p>You can then apply this policy at the controller level on the <code>AuthorizeAttribute<\/code> attribute as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Authorize(Policy = \"ShouldBeOnlyEmployee\")]\npublic IActionResult SomeMethod()\n{\n    \/\/Write your code here\n}<\/pre>\n\n\n\n<p>You can have policies with multiple claims as well. You should register them appropriately in the <code>ConfigureServices<\/code> method of the <code>Startup<\/code> class as shown in the code snippet given below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public void ConfigureServices(IServiceCollection services)  \n{  \n    services.AddMvc().SetCompatibilityVersion(\n          CompatibilityVersion.Version_2_1);  \n    services.AddAuthorization(options =&gt;  \n    {  \n        options.AddPolicy(\"CustomSecurityPolicy\", policy =&gt; \n             policy.RequireClaim(\"ShouldBeOnlyEmployee\"));  \n        options.AddPolicy(\"CustomSecurityPolicy\", policy =&gt; \n             policy.RequireClaim(\"IsAdmin\", \"true\"));  \n    });  \n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-requirements\">Requirements<\/h2>\n\n\n\n<p>Beneath the covers, both role-based and claims-based authorization techniques take advantage of a requirement, a handler, and a policy. In this and the subsequent sections each of these will be explored.<\/p>\n\n\n\n<p>A requirement comprises a collection of data parameters. These data parameters are used by a policy to evaluate the user identity. To create a requirement, you need to create a class that implements the <code>IAuthorizationRequirement<\/code> interface. The following code snippet illustrates a requirement for the <em>MinimumExp<\/em> policy &#8211; you will register this policy in a while.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public class MinimumExpRequirement : IAuthorizationRequirement\n{\n    public int MinimumExp { get; set; }\n    public MinimumExpRequirement(int experience)\n    {\n        MinimumExp = experience;\n    }    \n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-authorization-handlers\">Authorization Handlers<\/h2>\n\n\n\n<p>A requirement can have one or more handlers. An authorization handler is used to evaluate the properties of a requirement. To create an authorization handler, you should create a class that extends <code>AuthorizationHandler&lt;T&gt;<\/code> and implements the <code>HandleRequirementAsync()<\/code> method. The following code snippet shows how a typical authorization handler looks.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public class MinimumExpHandler : \n     AuthorizationHandler&lt;MinimumExpRequirement&gt;\n    {\n        protected override Task HandleRequirementAsync(\n               AuthorizationHandlerContext context, \n               MinimumExpRequirement requirement)\n        {\n            throw new NotImplementedException();\n        }\n    }<\/pre>\n\n\n\n<p>The following code snippet shows how you can write the necessary authorization logic in the <code>HandleRequirementsAsync<\/code> method to find a claim and evaluate the requirement.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public class MinimumExpHandler : \n          AuthorizationHandler&lt;MinimumExpRequirement&gt;\n    {\n        protected override Task HandleRequirementAsync(\n               AuthorizationHandlerContext context, \n               MinimumExpRequirement requirement)\n        {\n            var user = context.User;\n            var claim = context.User.FindFirst(\"MinExperience\");\n            if(claim != null)\n            {\n                var expInYears = int.Parse(claim?.Value);\n                if (expInYears &gt;= requirement.MinimumExp)\n                    context.Succeed(requirement);\n            }\n            return Task.CompletedTask;\n        }\n    }<\/pre>\n\n\n\n<p>Now, how do I know whether a handler executed successfully, i.e., what should a handler return? Well, if a requirement has been successfully evaluated, you may want to call the <code>Succeed<\/code> method on the <code>AuthorizationHandlerContext<\/code> instance and pass the requirement instance as a parameter to the method. In the code snippet given above, note how the <code>Succeed<\/code> method has been called.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-multiple-handlers-for-a-single-requirement\">Multiple Handlers for a Single Requirement<\/h2>\n\n\n\n<p>As I said earlier, a requirement can also have multiple handlers. You might want to use multiple handlers for a requirement when you need to evaluate the requirement based on multiple conditions. As an example, you might want to check if the user is an employee and if the age of the employee is more than 50 years. So, for each of these conditions, you need to have a separate handler.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public class EmployeeRequirement : IAuthorizationRequirement\n{\n   \/\/Write your code here\n}\npublic class EmployeeRoleHandler : \n         AuthorizationHandler&lt;EmployeeRequirement&gt;\n{\n    \/\/Write your code here to check if the user is an employee\n}\npublic class MinimumAgeHandler : \n         AuthorizationHandler&lt;EmployeeRequirement&gt;\n{\n    \/\/Write your code here to validate min age\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-registering-the-handler\">Registering the handler<\/h2>\n\n\n\n<p>You should register handlers in the services collection. To register the handler created earlier in this article, you should write the following code in the <code>ConfigureServices<\/code> method of the <code>Startup<\/code> class as shown in the code snippet below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public void ConfigureServices(IServiceCollection services)\n        {\n            \/\/Other code\n            services.AddSingleton&lt;IAuthorizationHandler, \n            MinimumExpHandler&gt;();\n        }<\/pre>\n\n\n\n<p>Note the usage of the <code>AddSingleton<\/code> method in the <code>ConfigureServices<\/code> method given above. When working with dependency injection in ASP.NET Core, you can specify the service lifetimes using <code>AddTransient<\/code>, <code>AddScoped,<\/code> or <code>AddSingleton<\/code> methods. This example uses the singleton lifetime. When using this type of service lifetime, the service instance will be created the first time it is requested. Subsequent requests to the service will reuse the same instance. To know more on service lifetimes in ASP.NET Core, you can take a look at this <a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/dependency-injection?view=aspnetcore-2.2\">article<\/a>.<\/p>\n\n\n\n<p>Here&#8217;s the complete code listing of the <code>ConfigureServices<\/code> method \u2013 both the policy and the handler is registered with the pipeline.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public void ConfigureServices(IServiceCollection services)\n        {      services.AddMvc().SetCompatibilityVersion(\n               CompatibilityVersion.Version_2_1);\n            services.AddAuthorization(options =&gt;\n            {\n                options.AddPolicy(\n                    \"MinExperience\", policy =&gt;\n                    policy.Requirements.Add(\n                          new MinimumExpRequirement(5)));\n            });\n            services.AddSingleton&lt;IAuthorizationHandler, \n                   MinimumExpHandler&gt;();\n        }<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-summary\">Summary<\/h2>\n\n\n\n<p>The authorization model in ASP.NET Core has had a major upgrade with the introduction of a simple, declarative, policy-based authorization model. Policy-based authorization is flexible and helps you to build a loosely coupled security model by decoupling the authorization and application logic. Incidentally, ASP.NET Core supports both role-based and policy-based authorization. This article examined the policy-based authorization model, its benefits, and how to work with it in ASP.NET Core.<\/p>\n\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs: Policy-based Authorization in ASP.NET Core \u2013 A Deep Dive<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. What is the difference between role-based and policy-based authorization in ASP.NET Core?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Role-based authorization ([Authorize(Roles = &#8220;Admin&#8221;)]) is a simple string comparison against the user&#8217;s role claims. It works well for basic access control but cannot express compound conditions (&#8216;user must be in Admin role AND have a PremiumAccount claim&#8217;). Policy-based authorization defines named policies that encapsulate authorization logic as requirements &#8211; objects evaluated by handlers. Policies can combine multiple requirements, reuse handler logic, and be applied declaratively with [Authorize(Policy = &#8220;PolicyName&#8221;)] or imperatively with IAuthorizationService.AuthorizeAsync.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. How do I create a custom authorization requirement in ASP.NET Core?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Implement IAuthorizationRequirement &#8211; this is a marker interface with no required methods, so the requirement class just holds the data the handler needs. For example: public class MinimumAgeRequirement : IAuthorizationRequirement { public int MinimumAge { get; } public MinimumAgeRequirement(int age) { MinimumAge = age; } }. Then write a handler that inherits AuthorizationHandler&lt;MinimumAgeRequirement&gt;, override HandleRequirementAsync, and call context.Succeed(requirement) if the condition is met. Register both the requirement (in policy definition) and the handler (with services.AddSingleton&lt;IAuthorizationHandler, MinimumAgeHandler&gt;()) in Startup.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. How do I register and apply an authorization policy in ASP.NET Core?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Register policies in services.AddAuthorization(options =&gt; { options.AddPolicy(&#8220;PolicyName&#8221;, policy =&gt; policy.RequireClaim(&#8220;ClaimType&#8221;, &#8220;value&#8221;)); }); or policy.AddRequirements(new CustomRequirement()). Apply with [Authorize(Policy = &#8220;PolicyName&#8221;)] on a controller or action. For imperative evaluation, inject IAuthorizationService and call AuthorizeAsync(user, resource, &#8220;PolicyName&#8221;). Minimum configuration requires both the policy definition and any custom handlers registered as IAuthorizationHandler services.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. Can a single requirement have multiple authorization handlers in ASP.NET Core?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Yes. Multiple handlers can be registered for the same requirement &#8211; useful when the requirement can be satisfied through different mechanisms (e.g., either a user role check or an API key check). ASP.NET Core evaluates all registered handlers for a requirement; the requirement succeeds if any handler calls context.Succeed(). To require all handlers to succeed, use context.Fail() in handlers that should block &#8211; but note that one Fail() overrides all Succeed() calls. Multiple handlers are registered individually with DI, each as a separate IAuthorizationHandler service.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Implement policy-based authorization in ASP.NET Core: build custom authorization requirements, write authorization handlers, register policies in middleware, and use claims-based authorization. Complete C# code throughout.&hellip;<\/p>\n","protected":false},"author":221905,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":true,"footnotes":""},"categories":[143538,53],"tags":[95509],"coauthors":[50381],"class_list":["post-82839","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-featured","tag-standardize"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82839","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221905"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=82839"}],"version-history":[{"count":12,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82839\/revisions"}],"predecessor-version":[{"id":109759,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82839\/revisions\/109759"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=82839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=82839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=82839"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=82839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}