0

In MVC 5 I controlled Menu Item (sitemap) visibility based on the controllers they are authorized to access.

I had a Module Management Page for assigning and un-assigning permission to each controller.

My AuthorizeAttribute looked like this:

public sealed class PermissionAttribute : AuthorizeAttribute {
    public string Module { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext) {
        if (!base.AuthorizeCore(httpContext)) {
            return false;
        }

        var moduleManager = new ApplicationModuleManager();
        var userId = httpContext.User.Identity.GetUserId();

        return moduleManager.IsUserAccessibleModule(Convert.ToInt32(userId), Module);
    }

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

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated) {
            base.HandleUnauthorizedRequest(filterContext);
            return;
        }

        filterContext.Result = new RedirectToRouteResult(
                                   new RouteValueDictionary
                                   {
                                       { "action", "AccessDenied" },
                                       { "controller", "Error" },
                                       { "area", "" }
                                   });
    }
}

And in the controller:

[Permission(Module = "Admin")]

In MVC 6, base on this question and this doc, I need to write a authorization requirements.

public class ModuleAuthorizationHandler : AuthorizationHandler<ModuleRequirement> {
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ModuleRequirement requirement) {
        if (!context.User.Identity.IsAuthenticated) { 
            return Task.CompletedTask;
        }

        //Do Module check

        return Task.CompletedTask;
    }
}

services.AddAuthorization(options => {
            options.AddPolicy("Module", policy => policy.Requirements.Add(new ModuleRequirement()));
        });


[Authorize(Policy = "Module")]

How do I pass in the Module name like this: [Permission(Module = "Admin")]for each controller? or is there a better way of doing this?

Note: I'm implementing it this way because my Roles are dynamic, it can be renamed, deleted, and new ones can be added, but Modules are static.

Community
  • 1
  • 1
capiono
  • 2,875
  • 10
  • 40
  • 76
  • 2
    my navigation component for asp.net core might interest you https://github.com/joeaudette/cloudscribe.Web.Navigation – Joe Audette Oct 05 '16 at 16:53
  • Joe, how do you use JsonNavigationTreeBuilder without having to change your libraries? – capiono Oct 06 '16 at 12:05
  • you would call services.AddScoped(); before calling services.AddCloudscribeNavigation(Configuration.GetSection("NavigationOptions")); but bear in mind jsonnavigationtreebuilder is not as well tested, I'm using xml in my own projects – Joe Audette Oct 06 '16 at 12:53
  • Joe, your component works great in mapping out the navigation. The roles viewRoles="Admin" are hardcoded in the xml file. This bring my back to my original question, does your component support dynamic roles? or does it work with policy requirement? – capiono Oct 10 '16 at 10:51
  • using policy would require calling authorization service on every node, don't think that would be efficient. navigation does not enforce security it is just cosmetic to show and hide the menu so define policy with allowed roles for security and configure nav with roles for show and hide. or implement custom [INavigationNodePermissionResolver](https://github.com/joeaudette/cloudscribe.Web.Navigation/blob/master/src/cloudscribe.Web.Navigation/INavigationNodePermissionResolver.cs) or open an issue if you want to suggest more ways to filter the nav – Joe Audette Oct 10 '16 at 12:22

0 Answers0