26

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?

1
  • you should create custom role provider i suppose. But you sould have list of contollers and all methods in db. Commented May 7, 2015 at 11:25

2 Answers 2

20

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;
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

how to use SetPermissionsAttribute with action method ? what i need to pass along with SetPermissionsAttribute ?
It's been awhile,but if I remember correctly it's something like [SetPermissions="Action1, Action2"] but i'm not sure.
Everyone should take note that this was awhile ago and the actual LINQ queries could be improved upon, and the database context and user manager should be injected, or the repository should be injected (if using repository pattern).
Just my 2 cents tip, generally it is not a good idea to make a call to a database from an attribute.
@Tohid but how does the default MVC Authorize attribute check your role etc without reading something from a database??
|
11

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.

2 Comments

I think I know where you're going with this, but for the sake of others who can gain knowledge from this q/a, can you edit your answer to make it more holistic (like include the logic of authorizing a user, maybe also include a list of IdentityRoles from the db as an example), and then I'll mark it as accepted.
If you use an implementation similar to the above, you might consider doing return isUserAuthorized; since you want to make certain that you return false when the user has not been granted access.

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.