Imperative authorization lets application code decide whether an operation may continue by explicitly calling authorization logic. It is useful when authorization depends on a resource that must be loaded first, such as a recipe the current user wants to edit. section 24.5.1 section 24.4.2
A typical resource-based authorization flow is:
- Inject IAuthorizationService into the endpoint or service. section 24.5.1
- Load the resource before making the authorization decision. section 24.5.1 section 24.4.2
- Call AuthorizeAsync with the ClaimsPrincipal user, resource, and policy name. section 24.5.1
- Continue when AuthorizationResult.Succeeded is true; otherwise return ForbidResult. section 24.5.1
Editing a recipe
An Edit Razor Page retrieves a Recipe, evaluates the CanManageRecipe policy against User and that recipe, then blocks execution when authorization fails. Traditional web apps may redirect to an access-denied page, while API apps typically return HTTP 403. section 24.5.1
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
}
}
Inspect the annotated Razor Page listing showing dependency injection, resource loading, AuthorizeAsync, and the failed-authorization branch. section 24.5.1
