title: Roles in Authorize Attribute does not work as expected in MVC 4
body: <p>(I am new to ASP.NET MVC 4 and prior to this project, I was used to working with WebForms with <code>&lt;authentication mode="none"&gt;</code>).</p>
  
  <p>I have a database in which I have specific roles against a user entity like <code>ADMIN</code> and <code>SUBADMIN</code> . I have separate controllers in my project to deal with different views for the different roles for example, <code>AdminController</code> and <code>SubAdminController</code> I can successfully redirect users to the respective views according to their roles.</p>
  
  <p>My issue is that when the users have logged in they can even access pages which they are not privileged to access.This implies that may be I have not set up authorization properly.</p>
  
  <p><strong>What I have tried?</strong></p>
  
  <p>I have tried the authorized attribute with ADMIN role filter so that only admins are authorized to view the respective views like:</p>
  
  <pre><code>[Authorize(Roles="ADMIN")]
      public class AdminController : BaseController
      {
      ....
      }
  </code></pre>
  
  <p>This redirects the user even if he is successfully authenticated to the login page which is configured in web.config like this:</p>
  
  <pre><code> &lt;authentication mode="Forms"&gt;
        &lt;forms loginUrl="~/Home/Index" timeout="2880" /&gt;
      &lt;/authentication&gt;
  </code></pre>
  
  <p>Note that if I just use <code>[Authorize]</code> instead then it works but even SubAdmin can gain access to the Admin views.</p>
  
  <p>I have tried configuring the authorization in Web.config too like this:</p>
  
  <pre><code>&lt;location path="Admin"&gt;
      &lt;system.web&gt;
  
        &lt;authorization&gt;
          &lt;allow roles="ADMIN"/&gt; 
  
          &lt;deny users="*"/&gt; 
        &lt;/authorization&gt;
  
      &lt;/system.web&gt;
    &lt;/location&gt;
  </code></pre>
  
  <p>This has lead to same results as using <code>[Authorize(Roles="ADMIN")]</code>.</p>
  
  <p>Note that if I console out the following </p>
  
  <p><code>User.Identity.ToGenericUserIdentity().RoleName;</code> in my <code>AdminController</code> then I get <code>ADMIN</code> and i can use it in my action methods to re-check whether the user is actually an admin or sub admin but that is not the correct way to write it down as checks in all my action methods.</p>
  
  <p><strong>Related classes:</strong></p>
  
  <pre><code>[Serializable]
      public class GenericUser
      {
  
          public bool IsInRole(string role) { return false; }
  
  
  
          public string RoleName { get; set; }
          public int UserID { get; set; }
          public string UserName { get; set; }
      }
  
      [Serializable]
      public class GenericUserIdentity : IIdentity
      {
          private GenericUser genericUser;
          private FormsAuthenticationTicket ticket;
  
          public GenericUserIdentity(FormsAuthenticationTicket ticket)
          {
              var serializer = new JsonSerializer();
              var reader = new JsonTextReader(new StringReader(ticket.UserData));
              genericUser = serializer.Deserialize&lt;GenericUser&gt;(reader);
              this.ticket = ticket;
          }
  
          public string AuthenticationType
          {
              get { return "Custom"; }
          }
  
          public bool IsAuthenticated
          {
              get { return ticket != null; }
          }
  
          public string Name
          {
              get { return genericUser.UserName; }
          }
  
          public string RoleName
          {
              get { return genericUser.RoleName; }
          }
  
          public int UserID
          {
              get { return genericUser.UserID; }
          }
  
  
  
      }
  
  public static class IdentityExtension
  {
      public static GenericUserIdentity ToGenericUserIdentity(this IIdentity identity)
      {
          var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
          var ticketInfo = FormsAuthentication.Decrypt(cookie.Value);
          return new GenericUserIdentity(ticketInfo);
      }
  }
  </code></pre>
  
  <p><strong>And how do I authenticate?</strong></p>
  
  <p>In my <code>HomeController</code> which shows the login page on Index() action, I have set up a HttpPost Index action like this:</p>
  
  <pre><code>  public ActionResult Index()
          {
              return View();
          }
   [HttpPost]
          public ActionResult Index(string username,string password)
          {
  
              UserInformation userInfo = _userProvider.FindUserByName(username);
  
              OrderProvider orderProvider = new OrderProvider(new OrderRepository());
  
              if (userInfo != null &amp;&amp; string.Equals(userInfo.Password, password,StringComparison.Ordinal))
              {
                  if (userInfo.isEnabled)
                  {
                      GenericUser genericUser = new GenericUser() { UserName = userInfo.Email, UserID = userInfo.UserID, RoleName = userInfo.RoleName };
  
                      Response.SetAuthCookie&lt;GenericUser&gt;(genericUser.UserName, genericUser);
  
                      if (userInfo.RoleName == "ADMIN")
                      {
                          return RedirectToAction("Index", "Admin");
                      }
                      else if (userInfo.RoleName == "USER")
                      {
                          return RedirectToAction("Index", "Customer");
                      }
                      else if (userInfo.RoleName == "DRIVER")
                      {
                          return RedirectToAction("Index", "Driver");
                      }
                      else if (userInfo.RoleName == "SUBADMIN")
                      {
                          return RedirectToAction("Index", "SubAdmin");
                      }
                  }
  
  
  
              }
  
              ViewBag.Error = true;
  
              return View("Index");
  
          }
  </code></pre>
  
  <h2>Edit</h2>
  
  <p>Finally overriding the <code>AuthorizeCore</code> method of my custom attribute worked for me.</p>
  
  <pre><code>public enum Role
      {
          ADMIN, SUBADMIN, USER, DRIVER
      }
  
      [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
      public class AuthorizeUser : AuthorizeAttribute
      {
          public AuthorizeUser(params object[] roles)
          {
              if (roles.Any(r =&gt; r.GetType().BaseType != typeof(Enum)))
                  throw new ArgumentException("roles");
  
              this.Roles = string.Join(",", roles.Select(r =&gt; Enum.GetName(r.GetType(), r)));
          }
  
  
  
  protected override bool AuthorizeCore(HttpContextBase httpContext)
          {
              var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
              var ticketInfo = FormsAuthentication.Decrypt(cookie.Value);
  
              GenericUserIdentity iden = new GenericUserIdentity(ticketInfo);
              if (Roles.Contains(iden.RoleName))
                  return true;
              else
                  return false;
          }
          }
  </code></pre>