Using forms authentication, I am filling the UserData
field with a serialized CustomIdentitySerializer
object.
The user logs in, and I have verified that Membership.ValidateUser()
works just fine.
I then begin populating the CustomIdentitySerializer
object and send it off to a static UpdateAuthenticationTicket
method in a static UserContext
class to test data retention - After Login() / User.Identity.IsAuthenticated:
// set auth ticket
UserContext.UpdateAuthenticationTicket(user.Username, serializeModel);
// get custom identity - user properties
string userName = UserContext.Identity.UserName;
// reset login attempts
Session["_LoginAttempts"] = 0;
return RedirectToAction("Index", "Dashboard");
Helper method:
/// <summary>
/// As we will want to update the UserData portion of the cookie while the
/// user is logged, this will be reused
///
/// Auth Ticket/Cookie's UserData property is the CustomIdentitySerializer object
/// </summary>
/// <param name="userName"></param>
/// <param name="userData"></param>
public static void UpdateAuthenticationTicket(string userName, CustomIdentitySerializer userData)
{
//var authUser = GetUser(userName);
JavaScriptSerializer serializer = new JavaScriptSerializer();
string userDataSerialized = serializer.Serialize(userData);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(30),
false,
userDataSerialized,
FormsAuthentication.FormsCookiePath);
// encrypt the ticket
string encTicket = FormsAuthentication.Encrypt(authTicket);
// create/set the cookie
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
HttpContext.Current.Response.Cookies.Add(faCookie);
}
userData
can change through the user's time on the site, so we will reuse this method whenever that data needs to be changed.
In Global.asax.cs
I have:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var fromsIdentity = new FormsIdentity(authTicket);
// Get the GenericPrincipal identity
IIdentity ui = HttpContext.Current.User.Identity;
CustomIdentity customIdentity = new CustomIdentity(ui.Name);
CustomPrincipal customPrincipal = new CustomPrincipal(ui.Name);
string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData;
// Set custom principal
HttpContext.Current.User = customPrincipal;
}
}
/// <summary>
/// Since we set current project and other custom user fields through the user experience,
/// these are saved in the authticket/cookie's UserData field as a CustomIdentitySerializer object type
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
// get the current cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var fromsIdentity = new FormsIdentity(authTicket);
JavaScriptSerializer serializer = new JavaScriptSerializer();
CustomIdentitySerializer userData = serializer.Deserialize<CustomIdentitySerializer>(authTicket.UserData);
CustomPrincipal customPrincipal = new CustomPrincipal(HttpContext.Current.User.Identity.Name);
customPrincipal.CustomIdentity.FirstName = userData.FirstName;
customPrincipal.CustomIdentity.LastName = userData.LastName;
customPrincipal.CustomIdentity.CurrentProject = userData.CurrentProject;
HttpContext.Current.User = customPrincipal;
}
}
}
I think this may have to do with the Principal provider not being set properly or rewritten.
After the cookie value is set, Application_AuthenticateRequest
get's hit, followed by Application_PostAuthenticateRequest
. This process occurs twice, then back to the Login page.
It seems that the code in Application_AuthenticateRequest
is not useful, as I'm not setting any properties there anyway.
The problem is that after the user is actually logged in, the RedirectToAction
goes back to http://localhost:1982/Account/Login?ReturnUrl=%2fDashboard
rather than appropriate page.
Are there any foreseeable issues in having updating the cookie from the static UserContext
class?
Some assistance on this please on how to clean this up and getting working?
Thanks.
-- UPDATE --
In looking at the authCookie
object in Application_PostAuthenticateRequest
, Expires
is set to {1/1/0001 12:00:00 AM}
. Regardless, the authTicket
cookie expiration is correct - 30 minutes from time of creation. So that cookie is there.
What else?
-- UPDATE --
In looking at the cookie version, I notice a difference. As soon as I set the cookie in UpdateAuthenticationTicket
, I check:
authTicket.Version =
and
FormsAuthentication.Decrypt(HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value).Version = 2
Not sure why there are two versions, if someone can please explain that as well? I tried setting the cookie with version=2 - same issue.
In further messing around with this, I moved the code over from
Application_PostAuthenticateRequest
toApplication_AuthenticateRequest
and everything seems to work fine now:Can someone please explain why this is, as so many of the references I have found for this indicate to put this code in
Application_PostAuthenticateRequest
???