MVC4 Custom Forms Authentication - Unable to cast
System.Web.HttpContext.Current.User as CustomPrincipal
I'm building a website in .Net MVC4 and am trying to implement my own
forms authentication using a CustomPrincipal object.
Here is my Login method...
public void Login(string email)
{
var user = _userManager.GetUserByEmail(email);
var encryptedCookieContent = FormsAuthentication.Encrypt(new
FormsAuthenticationTicket(1, user.Email, DateTime.Now,
DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
false, user.Id + "|" + user.AccountId + "|" + user.RoleId + "|" +
user.Role.Name, FormsAuthentication.FormsCookiePath));
var formsAuthenticationTicketCookie = new
HttpCookie(FormsAuthentication.FormsCookieName,
encryptedCookieContent)
{
Domain = FormsAuthentication.CookieDomain,
Path = FormsAuthentication.FormsCookiePath,
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL
};
HttpContext.Current.Response.Cookies.Add(formsAuthenticationTicketCookie);
}
This is my Custom Principal
public class CustomPrincipal : IPrincipal
{
public CustomPrincipal(IIdentity identity, int userId, int accountId,
string role, int roleId)
{
Identity = identity;
Role = role;
RoleId = roleId;
UserId = userId;
AccountId = accountId;
}
public bool IsInRole(string role)
{
return Role == role;
}
public bool IsInRole(int roleId)
{
return RoleId == roleId;
}
public IIdentity Identity { get; private set; }
public string Role { get; private set; }
public int RoleId { get; private set; }
public int UserId { get; private set; }
public int AccountId { get; private set; }
}
I'm not implementing a custom instance of Identity, I'm just reusing the
GenericIdentity. In my Global.asax file I've got my
Application_AuthenticateRequest method rigged up like this...
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
var formsCookie =
Request.Cookies[FormsAuthentication.FormsCookieName];
if (formsCookie != null)
{
var ticket = FormsAuthentication.Decrypt(formsCookie.Value);
var principal = PrincipalConfig.CreatePrincipal(ticket);
System.Web.HttpContext.Current.User = Thread.CurrentPrincipal
= principal;
}
}
}
PrincipalConfig.CreatePrincipal is the method that puts together my custom
principal object. This basically just fills in userData... like this...
public static CustomPrincipal CreatePrincipal(FormsAuthenticationTicket
ticket)
{
var userData = ticket.UserData.Split('|');
var principal = new CustomPrincipal(new
GenericIdentity(ticket.Name), Convert.ToInt32(userData[0]),
Convert.ToInt32(userData[1]), userData[3],
Convert.ToInt32(userData[2]));
return principal;
}
So now, referring back to the Application_AuthenticateRequest in the
global.asax file, you can see that I'm taking my newly created
CustomPrincipal object and assigning it to
System.Web.HttpContext.Current.User.
After doing so, if I put the following in the immediate window while still
in the Application_AuthenticateRequest method...
System.Web.HttpContext.Current.User as CustomPrincipal
I am shown all of the data in my CustomPrincipal object just as I would
expect.
However, if I later (in some other controller action) attempt to access
the System.Web.HttpContext.Current.User and cast it as a CustomPrincipal
it is returning a null.
Again, for each request that is made in the application I am able to
decrypt the FormsAuthenticationTicket from the FormsAuthentication cookie
inside of the Application_AuthenticateRequest method and I find all of my
UserData. So it seems that the cookie is being created and read properly.
But when the new CustomPrincipal is assigned to
System.Web.HttpContext.Current.User, there seems to be some sort of
disconnect from that time to the time that I attempt to access it again
inside another controller.
Can anyone see what I might be doing wrong here?
Let me know if I need to clarify anything.
Thanks
No comments:
Post a Comment