MVC / ASP.Net Best Practices for Record-Level Authorization

Does anyone have any suggestions for a good methodology for providing authorization at the record level while maintaining separation of concerns on the ASP.Net MVC website?

With PrincipalPermission, you can decorate a method with

PrincipalPermission(SecurityAction.Demand, Role = "GroupLeader") 

Require that any visitor to this page be a member of the GroupLeader fixed role.

Alternatively, you can decorate the method:

 [ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Manage", Resource = "Group")] 

Require that any visitor to this page allow the overall management of the group.

However, none of them refers to a scenario in which the user may have permission to edit some groups, but not others. As far as I can tell, even if I implement a custom ClaimsAuthorizationManager , there is no way to access the method parameters to perform conditional authorization.

In addition, both of the above methods simply throw a SecurityException if the user does not have access, and does not allow the method to elegantly redirect the user to a page explaining what happened and what they can do to get the necessary authorizations.

Obviously, I also understand that I could just encode the authorization logic in the method itself and redirect accordingly, but I would prefer to separate this if possible, and keep the method code clean to handle the actual processing of the request and also be able to work within a framework that can be more widely applied.

So, is there a β€œready-made” way to handle this scenario, or do I need to implement a custom IAuthorizationFilter ? I think that I could handle both authorization at the write level and graceful forwarding, but without any parameters at the method level this would be essentially a mass expression of if ... else if .

+7
c # asp.net-mvc
source share
1 answer

The easiest way to deal with this situation is to create a property on your objects to store the "owner" or "creator" of the object. Then, when you request objects, you filter them. For example:

 public class Foo { public int Id { get; set; } ... public string Creator { get; set; } } 

Then:

 public ActionResult FooDetails(int id) { var foo = db.Foos.SingleOrDefault(m => m.Id == id && m.Creator == User.Identity.Name); if (foo == null) { return new HttpNotFoundResult(); } return View(foo); } 

It is not possible to process this through an authorization filter because you need to select a line to determine user rights. Then you must select the line inside the action again to send it to the view. In addition, you will need to do some acrobatics so that the filter can find out how it should choose, from where you could even check the permissions first. In action, you already select an object, so just set it based on whether the user "owns" it at the same time.

+1
source share

All Articles