AuthorizeAsync asynchronously checks whether a user may perform an action. It receives the ClaimsPrincipal, the resource being protected, and the policy to evaluate, then returns an AuthorizationResult. section 24.5.1
Use the result to control the request or the user interface:
- Check Succeeded before continuing. A failed server-side check should return ForbidResult, producing a 403 response or an access-denied redirect. section 24.5.1
- Pass the actual resource, such as a Recipe, when authorization depends on ownership or other resource data. section 24.5.1
- Use the result to hide an Edit link, but retain the server-side check because UI hiding does not prevent direct access. section 24.6
- Reuse the same authorization handlers from Razor Pages in minimal API endpoints, while considering filters or domain-level checks when endpoint logic is duplicated. section 25.6
Protecting a recipe deletion endpoint
Fetch the recipe, call AuthorizeAsync with the request user, recipe, and CanManageRecipe policy, return Results.Forbid() when Succeeded is false, and delete only after authorization succeeds. section 25.6
Listing 24.14 Using IAuthorizationService for resource-based authorization
[Authorize] #1
public class EditModel : PageModel
{
[BindProperty]
public Recipe Recipe { get; set; }
private readonly RecipeService _service;
private readonly IAuthorizationService _authService; #2
public EditModel(
RecipeService service,
IAuthorizationService authService) #2
{
_service = service;
_authService = authService; #2
}
public async Task<IActionResult> OnGet(int id)
{
Recipe = _service.GetRecipe(id); #3
AuthorizationResult authResult = await _authService #4
.AuthorizeAsync(User, Recipe, "CanManageRecipe"); #4
if (!authResult.Succeeded) #5
{ #5
return new ForbidResult(); #5
} #5
return Page(); #6
}
}
Follow a complete Razor Page example showing dependency injection, resource loading, AuthorizeAsync, and failed-request handling. section 24.5.1
