C# Academy · Lesson

Custom Authorization Requirements

Build custom requirements and handlers.

Lesson 4 of 413 steps

Custom Authorization Requirements is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

When Built-ins Are Not Enough

Some rules cannot be expressed with RequireRole or RequireClaim - for example "must be at least 18" or "must own this resource".

For these you write a custom requirement plus a handler.

// Rule: user must be older than a configurable minimum age

IAuthorizationRequirement

A requirement is a marker that carries the rule's data. It implements the empty IAuthorizationRequirement interface.

public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public int MinimumAge { get; }
    public MinimumAgeRequirement(int minimumAge) =>
        MinimumAge = minimumAge;
}

AuthorizationHandler

A handler contains the logic. Derive from AuthorizationHandler<TRequirement> and override HandleRequirementAsync.

public class MinimumAgeHandler
    : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        MinimumAgeRequirement requirement)
    {
        // logic goes here
        return Task.CompletedTask;
    }
}

Succeeding the Requirement

Inside the handler, inspect the user's claims. If the rule is satisfied, call context.Succeed(requirement). If not, simply return without calling it.

var dobClaim = context.User.FindFirst("birthdate");
if (dobClaim is null) return Task.CompletedTask;

var dob = DateTime.Parse(dobClaim.Value);
int age = DateTime.UtcNow.Year - dob.Year;
if (dob > DateTime.UtcNow.AddYears(-age)) age--;

if (age >= requirement.MinimumAge)
    context.Succeed(requirement);

return Task.CompletedTask;

Succeed, Not Fail

Prefer calling Succeed when satisfied and doing nothing otherwise. Only call context.Fail() when you want to guarantee failure regardless of other handlers for the same requirement.

// Soft: let other handlers also try
if (ok) context.Succeed(requirement);

// Hard: force failure no matter what
if (blocked) context.Fail();

Registering the Handler

Register handlers in DI as IAuthorizationHandler. They are usually singletons unless they depend on scoped services.

builder.Services.AddSingleton<
    IAuthorizationHandler, MinimumAgeHandler>();

Attaching to a Policy

Add the requirement to a named policy using AddRequirements (or Requirements.Add). The handler is matched by type automatically.

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AtLeast18", policy =>
        policy.AddRequirements(new MinimumAgeRequirement(18)));
});

Using the Policy

Apply it like any other named policy.

[Authorize(Policy = "AtLeast18")]
[HttpGet("age-restricted")]
public IActionResult Restricted() => Ok();

Resource-Based Authorization

To authorize against a specific instance (e.g. "only the document owner may edit"), use the resource overload. The resource is passed into the handler context.

public class OwnerHandler
    : AuthorizationHandler<OwnerRequirement, Document>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        OwnerRequirement requirement,
        Document resource)
    {
        var userId = context.User.FindFirstValue(
            ClaimTypes.NameIdentifier);
        if (resource.OwnerId.ToString() == userId)
            context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

Calling IAuthorizationService

Resource-based checks run imperatively inside an action via the injected IAuthorizationService.

public async Task<IActionResult> Edit(int id)
{
    var doc = await _db.Documents.FindAsync(id);
    var result = await _authz.AuthorizeAsync(
        User, doc, "DocumentOwner");
    if (!result.Succeeded) return Forbid();
    return Ok(doc);
}

Multiple Handlers per Requirement

A requirement can have several handlers; if any handler succeeds, the requirement is met. This models OR conditions cleanly (unless a handler calls Fail).

// e.g. allow if owner OR if admin role
services.AddSingleton<IAuthorizationHandler, OwnerHandler>();
services.AddSingleton<IAuthorizationHandler, AdminOverrideHandler>();

Quick Check

Test your understanding of handlers.

Recap

You built custom authorization:

  • A IAuthorizationRequirement holds the rule's data.
  • An AuthorizationHandler<T> contains the logic and calls Succeed.
  • Register the handler as IAuthorizationHandler and attach the requirement to a policy.
  • Resource-based handlers and IAuthorizationService authorize specific instances.

That completes the authorization course.

Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “Custom Authorization Requirements” lesson free?

Yes — the full text of “Custom Authorization Requirements” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “Custom Authorization Requirements”?

Build custom requirements and handlers. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Custom Authorization Requirements” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Role-Based Authorization
  2. Claims-Based Authorization
  3. Policy-Based Authorization
  4. Custom Authorization Requirements
← Back to C# Academy