IAuthorizationService lets an ASP.NET Core endpoint check authorization after it has loaded the resource being protected. This matters when permission depends on the resource itself—for example, when a user may edit only recipes they created. An [Authorize] attribute can require authentication before a Razor Page runs, but it cannot make that ownership decision before the recipe is loaded. section 24.5 section 24.5.1
Inject IAuthorizationService into the page model or endpoint handler. After loading the recipe, call AuthorizeAsync(User, recipe, "CanManageRecipe"). The arguments are the current ClaimsPrincipal, the resource, and the policy to evaluate. The returned AuthorizationResult has a Succeeded property; if it is false, return a forbid result rather than continuing with the edit or delete. section 24.5.1 section 25.6
The named policy must be defined separately, with a requirement and an authorization handler that evaluates it. The same resource-based policy and handlers can be used from Razor Pages and minimal API endpoints. section 24.5.1 section 25.6
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 delete endpoint loads the recipe, checks the current user against the CanManageRecipe policy, and deletes only when authorization succeeds. section 25.6
The result can also improve the UI: set a page-model property from Succeeded and show an Edit link only when the user is allowed to edit. Keep the server-side check. Hiding a link does not prevent someone from calling the endpoint directly. section 24.6 section 24.7
