liveBook · Manning

Policy

As explained in .NET in Action, Second Edition

An authorization policy is a set of access-control rules composed of requirements that determine whether an authenticated principal may perform an action.

An authorization policy is a named set of access-control requirements that determines whether an authenticated principal may perform an action. Apply different policies to read and write operations when authentication alone is too broad. section 9.6 section 9.7

Build policies from three cooperating parts:

  • Register a named policy with AddAuthorization, require an authenticated user, and select the JWT bearer authentication scheme. section 9.6
  • Attach the policy by name to controller actions with Authorize, allowing read actions and restricting mutations independently. section 9.6
  • Represent specialized access rules as requirements and evaluate them in authorization handlers. section 9.6 section 9.7

Authenticated reads, restricted writes

Apply an AuthenticatedUsers policy to GET actions and an OnlyMe policy to create, update, and delete actions. OnlyMe succeeds when the authenticated principal has a preferred_username claim matching the configured developer identity. section 9.6

Listing 9.20 Controller action-level authorization
[ApiController]
[Route("[controller]")]
public class CatalogController : ControllerBase           #1
{
  [HttpGet]
  [Authorize("AuthenticatedUsers")]                       #2
  public IAsyncEnumerable<Book> GetBooks(
      string? titleFilter = null)
  { /*...*/ }
  
  [HttpGet("{id}")]
  [Authorize("AuthenticatedUsers")]                       #2
  public Task<Book?> GetBook(int id)
  { /*...*/ }
  
  [HttpPost]
  [Authorize("OnlyMe")]                                   #3
  public async Task<Book> CreateBook(
    BookCreateCommand command)
  { /*...*/ }
  
  [HttpPatch("{id}")]
  [ProducesResponseType(StatusCodes.Status404NotFound)]
  [ProducesResponseType(StatusCodes.Status204NoContent)]
  [Authorize("OnlyMe")]                                   #3
  public async Task<IActionResult> UpdateBook(
    int id, BookUpdateCommand command)
  { /*...*/ }
  
  [HttpDelete("{id}")]
  [ProducesResponseType(StatusCodes.Status404NotFound)]
  [ProducesResponseType(StatusCodes.Status204NoContent)]
  [Authorize("OnlyMe")]                                   #3
  public async Task<IActionResult> DeleteBook(int id)
  { /*...*/ }
}

Shows policy names applied at individual controller actions so read and mutation permissions can differ. section 9.6

Listing 9.21 Creating authorization policies
using Microsoft.AspNetCore.Authorization;
  
builder.Services.AddAuthorization(options =>                 #1
{
  options.AddPolicy("AuthenticatedUsers",                    #2
    policyBuilder => {                                       #3
      policyBuilder
        .RequireAuthenticatedUser()                          #4
        .AddAuthenticationSchemes(                           #5
          JwtBearerDefaults.AuthenticationScheme);           #6
    });
  options.AddPolicy("OnlyMe",                                #7
    policyBuilder => {
      policyBuilder
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(
          JwtBearerDefaults.AuthenticationScheme)
        .AddRequirements(new OnlyMeRequirement());           #8
    });
});
builder.Services.AddSingleton<IAuthorizationHandler,         #9
  OnlyMeRequirementHandler>();                               #10
  
var app = builder.Build();                                   #11

Shows registration of named policies, authentication schemes, requirements, and the authorization handler service. section 9.6

Listing 9.22 Custom authorization requirement and handler
using Microsoft.AspNetCore.Authorization;
  
namespace ManningBooksApi;
  
public class OnlyMeRequirement :                     #1
  IAuthorizationRequirement { }                      #2
  
public class OnlyMeRequirementHandler :
  AuthorizationHandler<OnlyMeRequirement>            #3
{
  protected override Task HandleRequirementAsync(    #4
    AuthorizationHandlerContext context,             #5
    OnlyMeRequirement requirement)
  {
    if (context.User != null)                        #6
    {
      var emailClaim = context.User
        .FindFirst("preferred_username");            #7
      if (emailClaim != null
        && emailClaim.Value == "your@email.com")     #8
      {
        context.Succeed(requirement);                #9
      }
    }
  
    return Task.CompletedTask;                       #10
  }
}

Shows a custom requirement and handler that inspects an authenticated user's claim before calling Succeed. section 9.6

How .NET in Action, Second Edition covers it

How deep it goes
Defines policies, schemes, requirements, handlers, and claim checks, but stops short of broader policy design.
Examples
Uses AuthenticatedUsers and OnlyMe policies on catalog read and mutation actions, with a preferred_username claim check.
What it assumes
Assumes authenticated users, bearer tokens, and available claims; teaches policy requirements and handlers explicitly.
What you can do after
Build it from scratch by registering named ASP.NET Core policies and handlers, then applying them to controller actions.
How it connects
Connects authorization with authentication, JWT bearer tokens, claims, requirements, handlers, and controller actions.

Also explained in

Compare how 13 books explain policy →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of .NET in Action, Second Edition. The section links point to the parts of the book it draws on.