Search code examples
c#asp.net-mvcmodel-view-controlleruserprincipal

Attempt to extend UserPrincipal in MVC not working


I've tried to extend the UserPrincipal method in MVC but I can't figure out why its not working.

My Code:

interface ICustomPrincipal : IPrincipal
{
    Guid AuthId { get; set; }
    Role UserRole { get; set; }
}
public 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 Guid AuthId { get; set; }
    public Role UserRole { get; set; }
}

public class CustomPrincipalSerializeModel
{
    public Guid AuthId { get; set; }
    public Role UserRole { get; set; }
}

My IdentityUser:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
    public Guid UserIdMatch { get; set; }
    public Role Role { get; set; }
}

So When a user is created they get a authId and a role.

When a user login / register:

var user = db.Users.Include(i => i.Role).FirstOrDefault(i => i.UserName == model.Username);
CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
serializeModel.AuthId = user.UserIdMatch;
serializeModel.UserRole = user.Role;

JavaScriptSerializer serializer = new JavaScriptSerializer();
string userData = serializer.Serialize(serializeModel);

FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,
    user.UserName,
    DateTime.Now,
    DateTime.Now.AddDays(1),
    false,
    userData
    );

string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(faCookie);

At last in my Global.asax I have the following code:

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();

        CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);

        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.AuthId = serializeModel.AuthId;

        HttpContext.Current.User = newUser;
    }
}

It should all be fine in my eyes, but when I call @((User as CustomPrincipalSerializeModel).AuthId) on any page, It throws the following error:

Object reference not set to an instance of an object.

Note: let say when i debug login. I dont get any error and i can see the cookie has the correct data.

Can someone point out what the problem is?


Solution

  • You are setting the user to be the CustomPrincipal but then you expect it to be the CustomPrincipalSerializeModel. Since the two are unrelated, this won't work for sure.

    I bet you meant

    @((User as CustomPrincipal).AuthId
    

    since the AuthId property seems to be present in both classes.