Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the ASP.Net MVC Login Redirect based on role?

I have the following code I've typed into the Account Controller in my MVC project and I am in both the administrator and manager roles. When I log in I get redirected back to my home index instead of being redirected to my AdminApp index. Any ideas where I'm going wrong in my code?

[AcceptVerbs(HttpVerbs.Post)]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
        Justification = "Needs to take same parameter type as Controller.Redirect()")]
    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
    {

        if (!ValidateLogOn(userName, password))
        {
                return View();
        }

        FormsAuth.SignIn(userName, rememberMe);
        if (!String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            if (User.IsInRole("Administrator") || (User.IsInRole("Manager")))
            {
                return RedirectToAction("Index", "AdminApp");
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }

        }
    } 
like image 768
Ben Avatar asked Dec 08 '09 09:12

Ben


2 Answers

The reason your code is not working as expected is because the User has technically not been signed in and authenticated yet. Say what? But you did call SignIn!

FormsAuth.SignIn(userName, rememberMe); - which in this case is just a wrapper for FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); - only sets the asp.net authorization cookie on the users browser as part of the response. It is only for requests after this point that the user's browser will have the cookie, causing the asp.net membership to properly set up the 'User' object. All of your code in the LogOn method is still assuming an anonymous user, so your IsInRole check fails and you are redirected home. Put your if statement on another page and after you've signed in, you'll see that now User.IsInRole works as expected. (And indeed, this is what you'd use User.IsInRole for, just not during the logon process)

So how to check during the actual logon process? Roles.IsUserInRole or Roles.GetRolesForUser are a couple of ways, eg.:

if (Roles.IsUserInRole(userName, "Administrator") || Roles.IsUserInRole(userName, "Administrator"))
{
    return RedirectToAction("Index", "AdminApp");
}

You must explicitly specify the user name of the user logging in, which will actually execute a query against the membership datastore. On that note, I believe the above code would as a result cause two queries to be executed, which you may find less than ideal. This is where Roles.GetRolesForUser might be a better option:

string[] roles = Roles.GetRolesForUser(userName);
if (roles.Contains("Administrator") || roles.Contains("Manager"))
{
    return RedirectToAction("Index", "AdminApp");
}

Hope that helps!

like image 79
Kurt Schindler Avatar answered Sep 20 '22 21:09

Kurt Schindler


I'm using VS 2013 and it's new Identity model, I ended up going with this:

foreach (IdentityUserRole identityUserRole in user.Roles)
{
   if (identityUserRole.RoleId == "AdminRoleId")
   {
     return RedirectToAction("Index", "Admin");
   }
   else if (identityUserRole.RoleId == "MemberRoleId")
   {
     return RedirectToAction("Index", "Members");
   }
 }
like image 25
MikeT Avatar answered Sep 22 '22 21:09

MikeT