How do I plug a custom roles manager into the AuthorizeAttribute?

91 Views Asked by At

I have an older database schema that I cannot change. It has a single user table with an integer field to designate user level where 1 is standard user and 5 is administrator. I'm writing an MVC front end and I want to use ASP.NET Identity. I've figured out everything else from research and the boilerplate code. I can't seem to figure out how to create a custom roles system. I realize it has something to do with implementing a role manager and role store. That's fine but how do I then connect that with MVC to get the AuthorizeAttribute to acknowledge my manager?

I apologize if this is obvious but I have done my research and I'm having trouble nailing it down.

2

There are 2 best solutions below

7
On BEST ANSWER

From your question, I'm assuming you already figured out how to create your role manager and you are only missing the config to actually use it. If my assumptions are wrong, let me know and I will add explanation on how to create the CustomRoleManager.

Web.config

<configuration>
  <system.web>
    <roleManager enabled="true" defaultProvider="CustomRoleProvider">
      <providers>
        <clear/>
        <add name="CustomRoleProvider"
             type="MyNamespace.CustomRoleProvider,
                   MyNamespace, Version=1.0.0.0, Culture=neutral"
             connectionStringName="MyConnectionString"
             enablePasswordRetrieval="false"
             enablePasswordReset="false"
             requiresQuestionAndAnswer="false"
             writeExceptionsToEventLog="false" />
      </providers>
    </roleManager>
  </system.web>
</configuration>
0
On

Here is the RoleProvider that I used, if anyone has the same trivial requirements. If you know of any reason why this implementation is not secure, please let me know. I used @Pluc's answer in my Web.Config to connect this provider to my application. It worked wonderfully.

public class AppRole : IRole<int>
{
    public AppRole(int a_id, string a_name)
    {
        Id = a_id;
        Name = a_name;
    }

    public int Id { get; private set; }
    public string Name { get; set; }
}

public class AppRoleProvider : RoleProvider
{
    private readonly IServiceLocator _container = UnityConfig.GetServiceLocator();
    private ITrainingRepository _repository; // Thin wrapper around my DbContext

    private AppRole[] _roles = new[]
        {
            new AppRole(0, "User"),
            new AppRole(5, "Admin"),
        };

    public AppRoleProvider()
    {
        ApplicationName = "TrainingCenter";

        _repository = _container.GetInstance<ITrainingRepository>();
    }

    public override string ApplicationName { get; set; }

    public override bool IsUserInRole(string username, string roleName)
    {
        var user = _repository.GetUserByUserName(username);
        if (user == null)
            return false;

        var role = _roles.FirstOrDefault(i => i.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase));

        if (role == null)
            return false;

        if (user.UserLevel >= role.Id)
            return true;

        return false;
    }

    public override string[] GetRolesForUser(string username)
    {
        var user = _repository.GetUserByUserName(username);
        if (user == null)
            return new string[] {};

        return _roles.Where(i => i.Id <= user.UserLevel).Select(i => i.Name).ToArray();
    }

    public override void CreateRole(string roleName)
    {
        // Does not create.
    }

    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    {
        // Does not delete.
        return false;
    }

    public override bool RoleExists(string roleName)
    {
        return _roles.Any(i => i.Name.Equals(roleName, StringComparison.OrdinalIgnoreCase));
    }

    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    {
        // Does not add user to role.
    }

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
    {
        // Does not remove users from roles.
    }

    public override string[] GetUsersInRole(string roleName)
    {
        // Does not get users in role.
        return new string[] {};
    }

    public override string[] GetAllRoles()
    {
        return _roles.Select(i => i.Name).ToArray();
    }

    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    {
        // Does not find users in role.
        return new string[] { };
    }

}