Click here to Skip to main content
14,158,462 members
Click here to Skip to main content
Add your own
alternative version


26 bookmarked
Posted 9 Apr 2013
Licenced CPOL

How to implement a custom IPrincipal in ASP.NET MVC 4 internet project

, 9 Apr 2013
Rate this:
Please Sign up or sign in to vote.
A simple tip on how to implement a custom IPrincipal in ASP.NET MVC 4 template project with WebMatrix.WebSecurity and OAuthWebSecurity.


This article explains a simple tip on how to customized the IPrincipal used in ASP.NET MVC4 internet application project template. You can try this tip if you want to attach additional information on the IPrincipal (Controller.User) for some purposes.


This tip is based from the solution I used in implementing custom identity in my ASP.NET MVC 3 project which I got from this thread:

The main solution is almost the same from the said thread but with just a few tweaks required to set data to additional IPrincipal properties when OAuthWebSecurity is used as authentication method.  

Using the code

Initially ASP.NET MVC 4 internet project template is configured to use both WebMatrix.WebSecurity (for local accounts) and OAuthWebSecurity (for external site accounts) for authentication. Also accounts data are getting saved in a UserProfile table which only have properties for user ID and username, and some predefined webpages_TABLES. 

This initial setup is not enough for us to achieve our goal: that is to attach additional information in the IPrincipal. In this example we will going to need to add the first name and last name info of the user but you can add any data to suit your needs.

We will need first a storage of the additional data we want to attach. To do this you can just simply add properties on the UserProfile class defined in AccountModels.cs. Or use any table then modify the InitializeSimpleMembershipAttribute.cs from the Filters folder and set your DBContext and table name:

public SimpleMembershipInitializer()

      using (var context = new UsersContext())
        if (!context.Database.Exists())
          // Create the SimpleMembership database without Entity Framework migration schema

      WebSecurity.InitializeDatabaseConnection("DefaultConnection", "YourDesiredTable", 
              "UserId", "UserName", autoCreateTables: true);
    catch (Exception ex)
      throw new InvalidOperationException("The ASP.NET Simple Membership database could " + 
        "not be initialized. For more information, please see " + 
        "", ex);

Another way is to leave the SimpleMembershipInitializer as it is and check this tutorial: 

If your data storage is now ready we can now start creating custom IPrincipal

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
    string FirstName { get; set; }
    string LastName { get; set; }
public class CustomPrincipal : ICustomPrincipal
    public IIdentity Identity { get; private set; }
    public CustomPrincipal(string username)
		this.Identity = new GenericIdentity(username);
	public bool IsInRole(string role)
		return Identity != null && Identity.IsAuthenticated && 
		   !string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);

	public string FirstName { get; set; }

	public string LastName { get; set; }

	public string FullName { get { return FirstName + " " + LastName; } }

public class CustomPrincipalSerializedModel
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

Then in the AccountController class, add this method. We will need this method to serialize the user data and attach it in a cookie: 

public void CreateAuthenticationTicket(string username) {     
      var authUser = Repository.Find(u => u.Username == username);  
      CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();
      serializeModel.FirstName = authUser.FirstName;
      serializeModel.LastName = authUser.LastName;
      JavaScriptSerializer serializer = new JavaScriptSerializer();
      string userData = serializer.Serialize(serializeModel);
      FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
      string encTicket = FormsAuthentication.Encrypt(authTicket);
      HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);

Call the above method: From the ExternalLoginCallback method: 

public ActionResult ExternalLoginCallback(string returnUrl)
      AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(
        Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
      if (!result.IsSuccessful)
        return RedirectToAction("ExternalLoginFailure");
      if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: true))
                        result.Provider, result.ProviderUserId));
        return RedirectToLocal(returnUrl);
      if (User.Identity.IsAuthenticated)
        // If the current user is logged in add the new account
        OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
        return RedirectToLocal(returnUrl);
        // User is new, ask for their desired membership name
        string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
        ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
        ViewBag.ReturnUrl = returnUrl;
        return View("ExternalLoginConfirmation", 
          new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });

In Register method: 

public ActionResult Register(RegisterModel model)
  if (ModelState.IsValid)
    // Attempt to register the user
        new {             
            UpdatedBy = 0, 
            UpdatedDate = DateTime.Today, 
            CreatedBy = 0, 
            CreatedDate = DateTime.Today 

      WebSecurity.Login(model.UserName, model.Password);
      return RedirectToAction("Index", "Home");
    catch (MembershipCreateUserException e)
      ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));

In ExternalLoginConfirmation method: 

OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
 OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
 return RedirectToLocal(returnUrl);    

And in the Login method: 

public ActionResult Login(LoginModel model, string returnUrl)
      if (ModelState.IsValid && WebSecurity.Login(model.UserName, 
                model.Password, persistCookie: model.RememberMe))
        return RedirectToLocal(returnUrl);
      // If we got this far, something failed, redisplay form
      ModelState.AddModelError("", "The user name or password provided is incorrect.");
      return View(model);

It's now time to read the serialized data from our cookie and replace the HttpContext.Current.User. Do this by overriding the Application_PostAuthenticateRequest method in project's Global.asax.cs .  

protected 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();
        if (authTicket.UserData == "OAuth") return;
        CustomPrincipalSerializedModel serializeModel = 
        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.Id = serializeModel.Id;
        newUser.FirstName = serializeModel.FirstName;
        newUser.LastName = serializeModel.LastName;
        HttpContext.Current.User = newUser;

To access the attached data from pages: 

@(User as CustomPrincipal).FullName

And from server:  

@(User as CustomPrincipal).FullName

Points of Interest 

Nothing clever from what I did actually, just a simple tip. 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Leo Dungca
Software Developer
Philippines Philippines
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionSource Code Pin
Member 125836622-Apr-17 5:49
memberMember 125836622-Apr-17 5:49 
GeneralMy vote of 5 Pin
Dan Randolph22-Jul-16 7:52
professionalDan Randolph22-Jul-16 7:52 
GeneralMy vote of 4 Pin
J.F.5-Jun-13 11:58
memberJ.F.5-Jun-13 11:58 
QuestionTwo things Pin
J.F.5-Jun-13 11:57
memberJ.F.5-Jun-13 11:57 
AnswerRe: Two things Pin
Member 127816157-May-18 8:31
memberMember 127816157-May-18 8:31 
QuestionGreat Post, But... Pin
Guilherme Morais18-May-13 14:28
memberGuilherme Morais18-May-13 14:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190518.1 | Last Updated 9 Apr 2013
Article Copyright 2013 by Leo Dungca
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid