Reputation: 310
I have a question similar to Owner based Authorization
Is it possible to use resource-based authorization or policy-based authorization to allow only the owner of a model to view/edit/delete it?
With something like
[Authorize(Policy = "OwnerAuthorization")]
public class EditModel : PageModel
Or do I have to add logic to every OnGet/OnPost on every page for handling the authorization?
Upvotes: 0
Views: 1334
Reputation: 25360
do I have to add logic to every OnGet/OnPost on every page for handling the authorization?
You don't have to, but for a better performance, you should add logic for every OnGet/OnPost on every page.
To authorize the request in the way of resource-based authorization
, we need firstly to know what the resource is, and only after that we can authorize the user against the resource and policy.
Typically, we need load the resource from the server and then we can know whether the resource belongs to the current user. As loading the resource from server is usually done within action method, we usually authorize the request within the action method. That's exactly what is described in the official document.
var authorizationResult = await _authorizationService .AuthorizeAsync(User, Document, "EditPolicy"); if (authorizationResult.Succeeded) { return Page(); } else if (User.Identity.IsAuthenticated) { return new ForbidResult(); } else { return new ChallengeResult(); }
However, if we choose to decorate the pagemodel with [Authorize(Policy = "OwnerAuthorization")]
only, and don't invoke the _authZService.AuthorizeAsync(User, resource, "OwnerAuthorization");
within the action method, we'll have to load the resource within the authorization handler( or a simple function). In other words, we'll query the database twice. Let's say an user wants to edit a Foo
model , and then make a HTTP GET request to /Foo/Edit?id=1
to show the form. The OnGetAsync(int? id)
method is :
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null){ return NotFound(); }
// load foo from database
Foo = await _context.Foos.FirstOrDefaultAsync(m => m.Id == id);
if (Foo == null){ return NotFound(); }
return Page();
}
Now the resource-based authorization will load the Foo entity from database and check the owner. If succeeds, the action method will then validate the model.id and load resource from the database again.
Upvotes: 1