0

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

kanazaca
  • 28
  • 3
  • 8
  • That's because it uses the IsUserInRole method of the role provider. Step into that method. – Cyberdrew Jun 16 '15 at 16:07
  • if i put a break point in that method ("IsUserInRole") still the same, dont pass through it. I added the method in the questions, take a look pls. – kanazaca Jun 16 '15 at 16:21
  • a bit late comment to this question, but in your example there is no way how to setup cacheTimeoutInMinutes > so i wonder if it is in default value (0) – cpoDesign Dec 27 '15 at 03:59

1 Answers1

0

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.

Joe
  • 122,218
  • 32
  • 205
  • 338
  • Thanks ;) I already implemented IsUserInRole in my custom RoleProvider and debug the GetType and yes it is of type System.Web.Security.RolePrincipal, print screen -> http://s21.postimg.org/3y21l6jyf/debug.png – kanazaca Jun 16 '15 at 16:32
  • @kanazaca - see update for some more debugging tips. – Joe Jun 16 '15 at 16:54
  • how can i check if the ProviderName returns my custom RoleProvider ? When i use User.IsInRole returns the wrong value, seems that is not using my custom role provider. – kanazaca Jun 17 '15 at 11:22
  • @kanazaca - does the name match what's in web.config (TicketsRoleProvider)? Is the Type of Roles.Providers[ProviderName] the correct type (Tickets.CustomRoleProvider)? Is it possible you have another assembly with this type? Try overriding the Initialize method in your custom RoleProvider and add a breakpoint in it to see if it's hit. Check that you've added your custom RoleProvider to the web.config in the application root, and not in a subdirectory (such as in the Views subdirectory) – Joe Jun 17 '15 at 11:33