ASP.NET MVC 5 Custom Role Provider Not Working?

3.6k views Asked by At

i have a problem with my custom role providor "string[] GetRolesForUser(string username)" method but the proccess dont go through it. My code is:

Controller (Just a piece of it):

[Authorize(Roles="Administrator")]
public class UsersController : AdminBaseController
{
    private IUsersRepository users;
    private IDepartmentsRepository departments;

    public UsersController()
    {
        this.users = new UsersRepository(new TicketsContext());
        this.departments = new DepartmentsRepository(new TicketsContext());
    }
}

Custom Role Provider:

public class CustomRoleProvider : RoleProvider
{
    public override bool IsUserInRole(string username, string roleName)
    {
        var userRoles = GetRolesForUser(username);
        return userRoles.Contains(roleName);
    }

    public override string[] GetRolesForUser(string username)
    {
        //Return if the user is not authenticated
        if (!HttpContext.Current.User.Identity.IsAuthenticated)
            return null;

        //Return if present in Cache
        var cacheKey = string.Format("UserRoles_{0}", username);
        if (HttpRuntime.Cache[cacheKey] != null)
            return (string[])HttpRuntime.Cache[cacheKey];

        //Get the roles from DB
        var userRoles = new string[] { };
        var user = db.Users.Where(u => u.email == username).FirstOrDefault();
        if (user != null)
        {
            if(user.access_level == 0)
            {
                userRoles = new[] { "Administrator" };
            }
            else
            {
                userRoles = new[] { "Normal" };
            }
        }

        //Store in cache
        HttpRuntime.Cache.Insert(cacheKey, userRoles, null, DateTime.Now.AddMinutes(_cacheTimeoutInMinutes), Cache.NoSlidingExpiration);

        // Return
        return userRoles.ToArray();
    }
}

Web.config

<!-- Custom Role Provider -->
<roleManager enabled="true" defaultProvider="TicketsRoleProvider">
  <providers>
    <add name="TicketsRoleProvider"
         type="Tickets.CustomRoleProvider"
         cacheTimeoutInMinutes="30" />
  </providers>
</roleManager>

I cant get it to work, and i dont know why.

Can anyone help me pls ?

Thanks

1

There are 1 answers

4
Joe On

I can't see anything obvious, but I would:

  • Remove the check for "HttpContext.Current.User.Identity.IsAuthenticated" in the GetRolesForUser method. This method should just get the roles for the username supplied as an argument.

  • To debug, I'd start by examining HttpContext.Current.User.GetType() inside a controller action method (one that isn't secured). Is it of type System.Web.Security.RolePrincipal?

  • You should implement IsUserInRole in your custom RoleProvider. The implementation can just check that the supplied role is in the array returned by GetRolesForUser. I don't think this is your problem though: IsUserInRole isn't used by RolePrincipal (though it is used by System.ServiceModel.Security.RoleProviderPrincipal if you use ASP.NET roles in a WCF service, so it's a good idea to implement it anyway.

UPDATE

You've confirmed HttpContext.Current.User is a RolePrincipal. I suggest you examine it closely using the debugger. In particular examine:

  • the ProviderName property, which should match the name of your custom RoleProvider.

  • the Identity property, which should match the name of the current user.

You might also try calling HttpContext.Current.User.IsInRole from code in your controller. The first time this is called, it should call your custom RoleProvider's GetRolesForUser method.

You can also try calling the RolePrincipal.SetDirty() method: this marks the cached role list as having been changed, and the next call to IsInRole or GetRoles should call your custom RoleProvider's GetRolesForUser method again.