Search code examples
asp.net-mvcauthenticationuser-roles

MVC 3 Authentication / Authorization: Roles missing


We use MVC 3. The default user management is not usable for us as our account info is stored in our own data-store and access goes via our own repository classes.

I'm trying to assign a principal add roles to the HttpContext.User and give out an authorization cookie.

Based on a code snipped I found I tried something like this:

if (UserIsOk(name, password))
{
    HttpContext.User =
        new GenericPrincipal(
            new GenericIdentity(name, "Forms"),
            new string[] { "Admin" }
        );
    FormsAuthentication.SetAuthCookie(name, false);

    return Redirect(returnUrl);
}

When the next request is done, the user is authenticated, but he is not in the "Admin" role. What am I missing?


Solution

  • I think you should implement FormsAuthenticationTicket. More info here : http://msdn.microsoft.com/en-us/library/aa289844(v=vs.71).aspx

    In Mvc it is quite similar.

    I have a class called UserSession that is injected into LoginController and that I use in LogOn action :

        [HttpPost, ValidateAntiForgeryToken]
    public ActionResult Index(LoginInput loginInput, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            return (ActionResult)_userSession.LogIn(userToLog, loginInput.RememberMe, CheckForLocalUrl(returnUrl), "~/Home");
        }
    }
    

    Here's my UserSession LogIn implementation (notice I put the "Admin" role hard coded for the example, but you could pass it as argument) :

    public object LogIn(User user, bool isPersistent, string returnUrl, string redirectDefault)
        {
            var authTicket = new FormsAuthenticationTicket(1, user.Username, DateTime.Now, DateTime.Now.AddYears(1), isPersistent, "Admin", FormsAuthentication.FormsCookiePath);
            string hash = FormsAuthentication.Encrypt(authTicket);
    
            var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
    
            if (authTicket.IsPersistent) authCookie.Expires = authTicket.Expiration;
    
            HttpContext.Current.Response.Cookies.Add(authCookie);
    
            if (!String.IsNullOrEmpty(returnUrl))
                return new RedirectResult(HttpContext.Current.Server.UrlDecode(returnUrl));
    
            return new RedirectResult(redirectDefault);
        }
    

    Then in the base controller I've overriden OnAuthorization method to get the cookie :

    if (filterContext.HttpContext.Current.User != null)
    {
       if (filterContext.HttpContext.Current.User.Identity.IsAuthenticated)
       {
          if( filterContext.HttpContext.Current.User.Identity is FormsIdentity ) 
          {
             FormsIdentity id = filterContext.HttpContext.Current.User.Identity as FormsIdentity;
             FormsAuthenticationTicket ticket = id.Ticket;
             string roles = ticket.UserData;
    
             filterContext.HttpContext.Current.User = new GenericPrincipal(id, roles);
          }
       }
    }
    

    I hope this helps. Let me know.