Is this the correct approach and can the users information such as address etc be stored in this cookie?
You are correct that Forms Authentication will by default store user details in an encrypted cookie, so it is a more secure than what you have now.
With Forms Authentication you are able to specify the string content that goes into the client cookie. However I would argue that the only information you should store in the cookie is the User Identifier and Role Identifier(s). This information should be all that is necessary to authenticate and authorise a user per request. Any extra information such as address will just add weight to the cookie and can be fetched from the service when required.
To make use of Forms Authentication, simply add the Authentication element to the web.config inside the system.web section:
<authentication mode="Forms">
<forms loginUrl="~/Login/Home" timeout="60" />
</authentication>
After you have called the service to validate the user, set the Cookie Data via the FormsAuthentication static class. Cookie data needs to contain the identifier of the user (if you want to display the user's name for example) and the Role identifier (explained below).
var username = // get name from service
var role = // get role from service
FormsAuthentication.SetAuthCookie(username + "-" + role, keepUserLoggedIn);
Use the same class to remove the cookie when the user signs out.
FormsAuthentication.SignOut();
My second question is, once a user is logged in, how do I know the role that they are in?
asp.net MVC provides a simple mechanism for permitting areas of your application only to specific users. By using the [Authorise] Attribute on any controller class or action method only logged in users will be allowed access - i.e users with a FormsAuthentication cookie present. Users who are not logged in will be redirected to the LoginUrl specified in the authenication element of the web.config.
The Authorise attribute also has an overload that will only permit users of a specific role to access the controller/method. This will allow only logged in users who are in the "Admin" role to access any action method of the controller.
[Authroise("Admin")]
public class EditController : Controller
{}
You then need to create your own implementation of the system interface RoleProvider. The interface contains many methods, but not all are necessary. The only method you need to implement to check which role a user is in is GetRolesForUser. This will be used by the [Authorise] attribute to determine if a user can view.
public class MyRoleProvider : RoleProvider
{
public override string[] GetRolesForUser(string username)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null && !String.IsNullOrEmpty(authCookie.Value))
{
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var roles = authTicket.UserData.Split(',')[1];
return roles.Split(';');
}
throw new MemberAccessException("User not logged in");
}
}
You then just need to tell your application to use your implementation of RoleProvider when the Authorise] Attribute kicks in. This is also done through the web.config inside the system.web element.
<roleManager defaultProvider="MyRoleProvider" enabled="true">
<providers>
<clear />
<add name="MyRoleProvider" type="My.Namespace.MyRoleProvider" />
</providers>
</roleManager>
Finally, once a user is logged in, should the entire site by https? Even areas that are open to everyone but being visited by the logged in user?
Ideally, yes. Once the user has logged in and you have set the FormsAuthentication cookie you need to protect that cookie from outside interception. To prevent this you should enforce the https protocol on all areas of your application. If a user's request is intercepted and a copy of the cookie is made then the 'man in the middle' can set the copy of the cookie in his browser and gain access to the protected areas of your site. With MVC you can use the [RequireHttpsAttribute] on any particular controllers or action methods similarly to the [Authorise] Attribute. In MVC4 there is an easy way to apply this 'Globally'. In your App_Start folder of your web project, find the FilterConfig class and include the following line to the RegisterGlobalFilters method:
filters.Add(new RequireHttpsAttribute());