Custom Security Script in ASP.NET MVC

I don't have much experience with this, and I really hope to get a good offer from you guys. I need to implement the following security scenario, and I would like to know how to do it.

Imagine that we have employees, managers and department heads. Both employees and supervisors appoint a ManagerId and point to the manager of the department to which they belong.

When a supervisor user logs in, I want him to see only records for employees belonging to the same ManagerId as his. If another manager of another ManagerId user logs in and manually deletes other employee information in the URL (for example: wwww.domain.com/employee/details/{id}), because his ManagerId! = Employee ManagerId I would like access was limited.

Does it make sense?

I started to print checks of all ActionMethods, for example:

public ActionResult Details(int id) { var employee = employeeRepository.Get(id) var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity; if(employee.managerId == user.managerId) { Do whatever... } else { Not allowed } } 

But typing this in all ActionMethods seems redundant and simple .. xxx ... I know there must be a better way.

+1
source share
2 answers

Here is a blow to the decision. It needs some cleaning, but should give you everything you need.

Create your own ActionFilter, and then decorate your methods with it.

 [ManagerIdAuthentication] public ActionResult Details(int id) { // Gets executed if the filter allows it to go through. } 

The following class can be created in a separate library so that you can include it in all your actions that require this verification.

 public class ManagerIdAuthentication : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { // the next line needs improvement, only works on an httpGet since retrieves // the id from the url. Improve this line to obtain the id regardless of // the method (GET, POST, etc.) var id = filterContext.HttpContext.Request.QueryString["id"]; var employee = employeeRepository.Get(id); var user = filterContext.HttpContext.User.Identity; if (employee.managerId == user.managerId) { var res = filterContext.HttpContext.Response; res.StatusCode = 402; res.End(); filterContext.Result = new EmptyResult(); //may use content result if want to provide additional info in the error message. } else { // OK, let it through. } } } 
+2
source

I had a similar problem in the past and I would consider permissions for each object. What I did was add an element to an object like:

 public bool CanUserAccess(User user) { return managerId == user.managerId; } 

Then, at the top of each action that provides access to the monitored resource:

 public ActionResult Details(int id) { var employee = employeeRepository.Get(id) var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity; if(!employee.CanUserAccess(user)) return new HttpUnauthorizedResult(); // Normal logic here } 

This, of course, is not ideal, but it centralizes the processing of permissions and allows you to easily increase complexity in the future (allow access to the chain, special rules for HR, etc.). You can also write another overload / extension to access the User.Identity property for a bit more automation (or at least handle type conversions).

Since I was dealing with ACLs, I would have additional methods / parameters to indicate the main nature of the action (e.g. Read, Write, Delete, Create, etc.).

+2
source

All Articles