views:

705

answers:

3

I am upgrading a site to use MVC and am looking for the best way to setup Authenication.

At this point i have the login working off of Active Directory, validating a username and password and then setting the auth cookie.

My question is how do i store the users role information at time of login in order for my controllers to see those roles as the user navigates.

[Authorize(Roles = "admin")]

I have no problem getting this list of roles from active directory. I just don't know where to put them so that the controllers will see them.

+1  A: 

When you authenticate your user, you generate a new GenericPrincipal instance. The constructor takes an array of strings which are the roles for the user. Now set HttpContext.Current.User equal to the generic principal and write the auth cookie, and that should do it.

Hope it helps.

Klaus

klausbyskov
+1  A: 

Could you not drop in either an authorization store role manager or find (e.g. on Codeplex) or write another Role Provider that works with Active Directory to get the groups information?

This would save you the hassle of authenticating the user, getting their roles, and then re-passing that information into the constructor, and would all happen automatically for you as part of the framework.

Zhaph - Ben Duguid
+9  A: 

Roles are added to the IPrincipal of the HttpContext. You can create a GenericPrincipal, parse the list of roles in the constructor and set it as HttpContext.User. The GenericPrincipal will then be accessible through User.IsInRole("role") or the [Authorize(Roles="role")] attribute

One way of doing this (in C#) is to add your roles as a comma separated string in the user data parameter when creating your authentication ticket

string roles = "Admin,Member";
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
  1,
  userId,  //user id
  DateTime.Now,
  DateTime.Now.AddMinutes(20),  // expiry
  false,  //do not remember
  roles, 
  "/");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
Response.Cookies.Add(cookie);

Then access the role list from the authentication ticket and create a GenericPrincipal from your Global.asax.cs

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(new Char[] { ',' });
      GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
      Context.User = userPrincipal;
    }
  }
}
David G
If Klaus hadn't answered well before you i would have given you the correct answer. This is the exact way i am doing things as well. Thanks for the detailed answer. Sorry it was a little to late.
Billy Logan
I guess this is not going to work for users that have cookies disabled ?
Omu
@Omu You can support cookieless authentication by simply modifying the Application_AuthenticationRequest() method to look for the authentication ticket in the URL if the cookie is not present. The important part is that the roles are stored in the encrypted authentication ticket.
David G