3

I want to create a dynamic role in ASP.NET MVC 5. I do not want to create hardcode roles in the authorization attribute .I want to create roles later.it's a test for my recruitment.Do you have sample code or video In this case? Just in ASP.NET MVC 5. Thanks in advance for your help

1 Answer 1

3

You mean you need dynamic authorization.

In order to do this.

1.You need to add two more tables(Except identity tables).

  1. AppContent (Columns:{Id, Resource, Function,Description})
  2. RoleRights (Columns:{Id, RoleName,AppContentId).

2.Create CustomAuthorizeAttribute

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class CustomAuthorize : AuthorizeAttribute
{
    //Custom named parameters for annotation
    public string Source { get; set; }//Controller Name
    public string Function { get; set; }//Action Name

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    { 
        //Is user logged in?
        if (httpContext.User.Identity.IsAuthenticated)
        {

             if ((!string.IsNullOrEmpty(ResourceKey)) && (!string.IsNullOrEmpty(OperationKey)))
            {
                //There are many ways to store and validate RoleRights 
                //1.You can store in Database and validate from Database.
                //2.You can store in user claim at the time of login and validate from UserClaims.
                //3.You can store in session validate from session

                //Below I am using database approach.
                var loggedInUserRoles = ((ClaimsIdentity) httpContext.User.Identity).Claims
                                        .Where(c => c.Type == ClaimTypes.Role)
                                        .Select(c => c.Value);

                //logic to check loggedInUserRoles has rights or not from RoleRights table
                return db.RoleRights.Any( x=> x.AppContent.Source == Source && x.AppContent.Function == Function && loggedInUserRoles.Contains( x.AppContent.RoleName));

            }

        }
        //Returns true or false, meaning allow or deny. False will call HandleUnauthorizedRequest above

        return base.AuthorizeCore(httpContext);
    }

    //Called when access is denied
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //User isn't logged in
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
            return;

        }
        //User is logged in but has no access
        else
        {
            filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary(new { controller = "Account", action = "NotAuthorized" })
            );
        }

    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Check for authorization

        if (string.IsNullOrEmpty(this.Source) && string.IsNullOrEmpty(this.Function))
        {
            this.Source = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            this.Function = filterContext.ActionDescriptor.ActionName;
        }

        base.OnAuthorization(filterContext);
    }
}

3. Assign CustomAuthorizeAttribute to the Controller Action

    [CustomAuthorize(Source= "Branch", Function = "Index")]
    public ActionResult Index()
    {
        return View(model);
    }

    [CustomAuthorize(Source = "Branch", Function = "Details")]
    public ActionResult Details(long? id)
    {
        return View(branch);
    }

    [CustomAuthorize(Source = "Branch", Function = "Create")]
    public ActionResult Create()
    { 
        return View();
    }

4.Setup all of your application content like Source(Controller) and Function(Action) in AppContent table.

5.Assign AppContents to a role for allowing to role to access this content.

6.Assign User to Role.

7.Run the application and test.

Sign up to request clarification or add additional context in comments.

2 Comments

Nice answer ! Could you tell me where do Resource and OperationKey come from ?
Also, Do you have any idea on how I could separate this Attribute in 2 parts ? One that would apply to the class, specifying for all actions the "Area" and the "Controller" ? And a second that would apply to methods, that would get the ActionName by relfection or something ? (this could also be done for the class attribute I guess) I could do this myself, but I'm a bit lost on how I could link the method attribute to get the class attribute and combine information stored in both attributes to apply athorization like your doing in your CustomAttribute. I'm trying to avoid repetition !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.