Skip to main content

How to Authorize in ASP.NET API using Authorization Policy with Requirements and Handler

· 2 min read
Adnan Rafiq
VP of Technology
Start and Finish Image

Image by @claybanks

Authorization Policy​

Authorizing the resource access is essential part of any API. The .NET provides you a perfect mental model which is easier to reason about. It has this flow:

  1. What is the name of your policy as string.
  2. What requirement the user must satisfy to qualify which implements the IAuthorizationRequirement interface.
  3. What is your handler responsible to evaluate, which inherits the AuthorizationHandler<UniqueIdHeaderRequirement> and register it.

Then Authorize attribute allows you to set a policy name when used on controller or action method. But if you are fan of Minimal API then fluent style is the way to go using RequireAuthorization.

How to define Authorization Policy?​

The AuthorizationOptions allows you to add policies with requirements using the AddAuthorization. Once the policy is defined and configured, it can be applied to the end point referred as resource.

Authorize using a Policy to verify that http header exists

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;

services.AddSingleton<IAuthorizationHandler, UniqueIdHeaderRequirement.UniqueIdHeaderRequirementAuthorizationHandler>();
// Required otherwise failure of auth handler will throw exception
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
services.AddAuthorization(options =>
{
options.InvokeHandlersAfterFailure = false;
options.AddPolicy("VerifyXUniqueIdHeader",
policyBuilder => {
policyBuilder.AddRequirements(new UniqueIdHeaderRequirement());
});
});
services.AddRouting();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(routeBuilder =>
{
//Fluent style
routeBuilder.MapGet("/", () => Results.Ok()).RequireAuthorization("VerifyXUniqueIdHeader");
//Attribute style - Same be done MVC controller or action
routeBuilder.MapGet("/hello", [Authorize(Policy = "VerifyXUniqueIdHeader")]() => Results.Ok());
});

app.Run();

internal class UniqueIdHeaderRequirement : IAuthorizationRequirement //IAuthorizationRequirement is a marker interface
{
// Handler gets called when the user is trying to access the resource.
internal class UniqueIdHeaderRequirementAuthorizationHandler : AuthorizationHandler<UniqueIdHeaderRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
UniqueIdHeaderRequirement requirement)
{
//for mvc filter context cast it to - AuthorizationFilterContext
if (context.Resource is HttpContext httpContext && !httpContext.Request.Headers.ContainsKey("x-unique-id"))
{
context.Fail();
return Task.CompletedTask;
}

context.Succeed(requirement);
return Task.CompletedTask;
}
}
}

Feedback​

I would love to hear your feedback, feel free to share it on Twitter.

Your team has features to ship. Production problems keep pulling them back.

  • Slow screens and reports frustrate users
  • The same timeouts and failures keep coming back
  • Your application struggles when demand peaks

I find and fix performance and stability problems across .NET and SQL Server, and use the causes we uncover to build AI guardrails that help catch those patterns in new code.

DM me on X with the problem taking the most time from your team. Watch my diagnostics walkthrough on On .NET Live.