Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically add roles to authorize attribute for controller

I need to enable my admin user to change access permissions for users on the fly, such that they can create new Roles and add permissions to those Roles.

I want to be able to create an Authorize attribute to stick above my controller class that I can add roles to from a database, so that I don't have to 'set' the roles during development, as in [Authorize(Roles="Role1, Role2")] etc.

So something like [Authorize(Roles = GetListOfRoles()]

I found this question - ASP.NET MVC Authorize user with many roles which does something similar but maybe there's a way to change this such that it gets a list of permissions/roles from the db?

like image 535
barnacle.m Avatar asked May 07 '15 11:05

barnacle.m


People also ask

Where can the Authorize attribute can be applied?

The Authorize attribute enables you to restrict access to resources based on roles. It is a declarative attribute that can be applied to a controller or an action method.

How does the Authorize attribute work?

The Authorize Attribute This means that once the request matches a supported route and is resolved to controller and method, it gets executed no matter what. Put another way, any public method defined on the controller class can be run if only the user calls the right URL.


2 Answers

This is how I pulled off an attribute that could authorize users per method based on the permissions of the role of that user. I hope this helps somebody else:

/// <summary>
/// Custom authorization attribute for setting per-method accessibility 
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SetPermissionsAttribute : AuthorizeAttribute
{
    /// <summary>
    /// The name of each action that must be permissible for this method, separated by a comma.
    /// </summary>
    public string Permissions { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        SalesDBContext db = new SalesDBContext();
        UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        ApplicationDbContext dbu = new ApplicationDbContext();

        bool isUserAuthorized = base.AuthorizeCore(httpContext);

        string[] permissions = Permissions.Split(',').ToArray();

        IEnumerable<string> perms = permissions.Intersect(db.Permissions.Select(p => p.ActionName));
        List<IdentityRole> roles = new List<IdentityRole>();

        if (perms.Count() > 0)
        {
            foreach (var item in perms)
            {
                var currentUserId = httpContext.User.Identity.GetUserId();
                var relatedPermisssionRole = dbu.Roles.Find(db.Permissions.Single(p => p.ActionName == item).RoleId).Name;
                if (userManager.IsInRole(currentUserId, relatedPermisssionRole))
                {
                    return true;
                }
            }
        }
        return false;
    }
}
like image 117
barnacle.m Avatar answered Oct 30 '22 20:10

barnacle.m


What about something like this:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyCustomAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        // Do some logic here to pull authorised roles from backing store (AppSettings, MSSQL, MySQL, MongoDB etc)
        ...
        // Check that the user belongs to one or more of these roles 
        bool isUserAuthorized = ....;

        if(isUserAuthorized) 
            return true;

        return base.AuthorizeCore(httpContext);
    }
}

You could use it with a database, or simply maintain a list of authorized roles in the web.config.

like image 38
Mick Walker Avatar answered Oct 30 '22 22:10

Mick Walker