I'm having trouble in getting the Authorize
attribute to work with roles. This is how I've decorated my controller:
[Authorize(Roles = "admin")]
public ActionResult Index()
{
...
}
and this is how I log a user in:
string roles = "admin";
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(30),
false,
roles
);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
HttpContext.Current.Response.Cookies.Add(cookie);
But my user is still denied access. Where am I going wrong?
I stumbled upon a similar example of your code: the highest voted answer of MVC - How to store/assign roles of authenticated users.
The AuthorizeAttribute calls the IsInRole method on the IPrincipal instance stored in HttpContext.User. By default IPrincipal has no roles, and in this case IsInRole will always return false. This is why access to your action is denied.
Since you have stored the user's roles into the FormsAuthenticationTicket's UserData property, you must extract the roles from the auth cookie and into a IPrincipal instance yourself. The highest voted answer of MVC - How to store/assign roles of authenticated users provides the code that you can add directly into your global.asax.cs file to do just this. I have repeated it below:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(',');
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}