2

Maybe I've overlooked this somewhere in the "documentation" for ASP.NET Identity (2.2.1), but I'm struggling to see the point in creating a controller and interfaces for managing Roles. I understand the point of managing users (CRUD + Assigning Roles), but as far as a CRUD for roles just doesn't make sense to me unless there's a way to dynamically detect access (IsInRole) for a controller at runtime. I have two questions:

1] Is there a point in dedicating the resources and time to create the CRUD for roles when you would have to configure the application in code in the first place to set the Authorize attribute to even set the role that should have access?

and

2] Is there a way to capture the moment in which the user requests an action from a controller or even the the instance of the controller as to possibly check permissions at that point from the DB?

clockwiseq
  • 4,049
  • 8
  • 33
  • 57
  • 1
    you can use Authorize attibute on class(controller) level even method level(action), so user can request the controller but not all actions – DanielVorph Apr 25 '16 at 18:03
  • Correct. That's the conundrum I'm in though. Why develop a method to manage roles, when they have to be hard-coded? – clockwiseq Apr 25 '16 at 18:09

2 Answers2

1

The best answer I could find on SO is this:

Dynamically add roles to authorize attribute for controller

This is exactly what I'm trying to accomplish which justifies my design of creating a CRUD for Roles. At that point, since I can dynamically add Roles to a Controller using the above method, I can dynamically create a Role and then include it in the requirement for a Controller to tighten access.

Community
  • 1
  • 1
clockwiseq
  • 4,049
  • 8
  • 33
  • 57
0
  1. I find roles very useful. Instead of decorating every controller, I put the role decorations on abstract classes I define for each section of a site. Then every controller used in a section, inherits from that section's abstract class.

  2. You could do that with an Http Module and override the AuthorizeRequest event. But I don't think doing a DB query on every request would be a good idea. The roles exist in memory, so role authorization would be extremely more efficient.

EDIT:
As per your comments, you could create a custom attribute to do that. Below is my idea of how it could be done. In the OnAuthorization event I would create an if block for every role. If the user is a member of that role, check to see if that role has access to the current controller. The example demonstrates that idea for just one role named Admin.

using System.Web.Mvc;
using System.Security.Claims;

namespace MyApp.Filters
{
    public class CustomAttribute : AuthorizeAttribute
    {
        private List<string> adminControllers;

        public CustomAttribute()
        {
            this.adminControllers = new List<string>();

            //This would be a DB call
            this.adminControllers.Add("MyApp.Controllers.AccountController");
            this.adminControllers.Add("MyApp.Controllers.AdministrationController");
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            //Get the roles for the current user
            var identity = (ClaimsIdentity)filterContext.HttpContext.User.Identity;
            var roles = identity.Claims.Where(c => c.Type == ClaimTypes.Role)
                        .Select(c => c.Value).ToList();

            //Check if current user has the Admin role
            if (roles.Contains("Admin"))
            {
                //Check if Admin role has access to current controller
                if (this.adminControllers.Contains(filterContext.Controller.ToString()))
                {
                    filterContext.Result = new RedirectResult("~/Home/Error");
                }
            }


        }
    }
}
Clint B
  • 4,162
  • 2
  • 15
  • 22
  • Thanks for the response Clint. So as far as #2, there's no way to efficiently manage dynamic role access, correct? If I have the permissions (think Group or Permission based access) configured in a table in my database, I would have to hit the DB each time a user attempted an action or to access a controller, correct? – clockwiseq Apr 25 '16 at 18:25
  • #1, as you answered, you have to hard-code each of the roles on either an abstract classes or a controller. Then what is the purpose of creating CRUD for Roles in an application? Hence why I'm so heavily wondering about #2. The purpose of security in an enterprise application should be to allow an administrator to impose access control for certain areas of an application for a particular user or group or role. If I don't know what roles exist, how can I implement them in my application? – clockwiseq Apr 25 '16 at 18:45
  • @-Keith - Yes to your question about #2. For your response about #1, I only allow administrators to access the role CRUD pages. Actually, I add a Profile table to the default Identity database and provide administrators the ability to create and assign profiles to users. My profiles are just a list of roles. I've also done sites where when a user registers, they are programmatically assigned default role(s). And again the role CRUD pages are for site administrators only. – Clint B Apr 25 '16 at 19:14
  • So maybe I asked my question in the wrong manner. Assigning roles to users is perfectly fine. I get that and I actually have implemented that already. The problem is defining what those roles have access to dynamically. I had actually thought about creating a Menu entity and include a collection of MenuItem entity that has Controller, Action, and Roles (list of IdentityRole) and if the user is in that role, they would have access to that menu item. The problem is defining that security at the controller level instead of menu item. That make sense? – clockwiseq Apr 25 '16 at 20:55
  • Ok, maybe I read your question too fast. I have an idea. I'll update my answer. – Clint B Apr 26 '16 at 11:13