clockwiseq
clockwiseq

Reputation: 4229

Dynamic Access Control with ASP.NET Identity

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?

Upvotes: 2

Views: 1994

Answers (2)

Clint B
Clint B

Reputation: 4700

  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");
                }
            }


        }
    }
}

Upvotes: 0

clockwiseq
clockwiseq

Reputation: 4229

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.

Upvotes: 1

Related Questions