Authorization decides whether a user may perform a requested action. It follows authentication: first establish who made the request, then check what that user may do. Think of an airport: proving your identity at check-in is different from showing a boarding pass to enter security or board a flight. section 24.1
In ASP.NET Core, start with the simplest rule: require a signed-in user. Put [Authorize] on an MVC action, controller, or Razor Page; it can also be applied globally. An unauthenticated visitor to a protected page is redirected to login. If a global rule also protects the login page, use [AllowAnonymous] to keep that page reachable. section 24.2.1
Choose the check that matches the decision:
- For a general permission, define a named policy with AddAuthorization(). A policy can require a claim or combine custom requirements and handlers. Apply it with [Authorize("PolicyName")]. section 24.4.2 section 24.7
- For permission over one particular item, load it first, then call IAuthorizationService.AuthorizeAsync() with the user, resource, and policy. A resource-based handler can compare the item’s creator with the current user. section 24.5 section 24.5.2
- For a minimal API endpoint, use RequireAuthorization(), optionally with a policy name. Use AllowAnonymous() for an exception; use IAuthorizationService inside the endpoint when the decision depends on a loaded resource. section 25.6
Who can edit a recipe?
Require login to create a recipe. To edit one, load the recipe and check whether the current user created it before allowing the edit. A policy that grants permission to edit every recipe cannot express that ownership rule on its own. A signed-in user who fails the check sees access denied; a visitor who is not signed in goes to login. section 24.5 section 24.5.2
Listing 25.3 Using resource authorization to protect a minimal API endpoint
app.MapDelete("recipe/{id}", async (
int id, RecipeService service,
IAuthorizationService authService, #1
ClaimsPrincipal user) => #2
{
var recipe = await service.GetRecipe(id); #3
var result = await authService.AuthorizeAsync( #4
user, recipe, "CanManageRecipe"); #4
if (!result.Succeeded) #5
{ #5
return Results.Forbid(); #5
} #5
await service.DeleteRecipe(id); #6
return Results.NoContent(); #6
});
#1 Injected to perform resource-based authorization
#2 The HttpContext.User claims principal for the request
#3 Fetches the recipe to access
#4 Performs resource-based authorization, passing in the user, resource, and the policy name
#5 If authorization failed, returns 403 Forbidden
#6 If authorization succeeded, executes the endpoint as normal
The minimal API deletion example loads the recipe, authorizes the user against that recipe, and returns Forbid() rather than deleting it when authorization fails. section 25.6
You can also hide an Edit link when a user lacks permission, making the interface less frustrating. Keep the server-side check: someone can type an edit URL directly or change its item ID. Hiding a link—or making IDs harder to guess—does not protect the resource. section 24.6 section 29.4.3



























