ASP.NET MVC – Set custom IIdentity or IPrincipal
I decided to use IPrincipal instead of IIdentity because it means I don’t have to implement both IIdentity and IPrincipal.
- Create the interface
123456interface ICustomPrincipal : IPrincipal{int Id { get; set; }string FirstName { get; set; }string LastName { get; set; }} - CustomPrincipal
1234567891011121314public class CustomPrincipal : ICustomPrincipal{public IIdentity Identity { get; private set; }public bool IsInRole(string role) { return false; }public CustomPrincipal(string email){this.Identity = new GenericIdentity(email);}public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }}
- CustomPrincipalSerializeModel – for serializing custom information into userdata field in FormsAuthenticationTicket object.
123456public class CustomPrincipalSerializeModel{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }}
- LogIn method – setting up a cookie with custom information
123456789101112131415161718192021222324252627if (Membership.ValidateUser(viewModel.Email, viewModel.Password)){var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First();CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();serializeModel.Id = user.Id;serializeModel.FirstName = user.FirstName;serializeModel.LastName = user.LastName;JavaScriptSerializer serializer = new JavaScriptSerializer();string userData = serializer.Serialize(serializeModel);FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1,viewModel.Email,DateTime.Now,DateTime.Now.AddMinutes(15),false,userData);string encTicket = FormsAuthentication.Encrypt(authTicket);HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);Response.Cookies.Add(faCookie);return RedirectToAction("Index", "Home");}
- Global.asax.cs – Reading cookie and replacing HttpContext.User object, this is done by overriding PostAuthenticateRequest
1234567891011121314151617181920protected void Application_PostAuthenticateRequest(Object sender, EventArgs e){HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];if (authCookie != null){FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);JavaScriptSerializer serializer = new JavaScriptSerializer();CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);newUser.Id = serializeModel.Id;newUser.FirstName = serializeModel.FirstName;newUser.LastName = serializeModel.LastName;HttpContext.Current.User = newUser;}}
- Access in Razor views
123@((User as CustomPrincipal).Id)@((User as CustomPrincipal).FirstName)@((User as CustomPrincipal).LastName)
and in code:
1 2 3 |
(User as CustomPrincipal).Id (User as CustomPrincipal).FirstName (User as CustomPrincipal).LastName |
I think the code is self-explanatory. If it isn’t, let me know.
Additionally to make the access even easier you can create a base controller and override the returned User object (HttpContext.User):
1 2 3 4 5 6 7 |
public class BaseController : Controller { protected virtual new CustomPrincipal User { get { return HttpContext.User as CustomPrincipal; } } } |
and then, for each controller:
1 2 3 4 |
public class AccountController : BaseController { // ... } |
which will allow you to access custom fields in code like this:
1 2 3 |
User.Id User.FirstName User.LastName |
But this will not work inside views. For that you would need to create a custom WebViewPage implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public abstract class BaseViewPage : WebViewPage { public virtual new CustomPrincipal User { get { return base.User as CustomPrincipal; } } } public abstract class BaseViewPage<TModel> : WebViewPage<TModel> { public virtual new CustomPrincipal User { get { return base.User as CustomPrincipal; } } } |
Make it a default page type in Views/web.config:
1 2 3 4 5 6 7 8 |
<pages pageBaseType="Your.Namespace.BaseViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> </namespaces> </pages> |
and in views, you can access it like this:
1 2 |
@User.FirstName @User.LastName |