2

How can I set global user data that retain some information like name, lastname, etc through pages? If I use session variable it expires before auth cookie

thanks!

Santiago
  • 2,190
  • 10
  • 30
  • 59
  • How long do you want it to persist? Across sessions? – Roman May 08 '11 at 01:58
  • yes, across auth session, I did use "session" variable but expires earlier – Santiago May 08 '11 at 02:16
  • You'll need to store it to a database or some other form of persistent storage. – Roman May 08 '11 at 02:19
  • Ok, but how to get the DB info across all controllers without having to write code on each one? – Santiago May 08 '11 at 02:21
  • 4
    Refactor your code so only one (or a few) controllers need access to this information and use something like the `RenderPartial` method to make it show up on all pages. – Roman May 08 '11 at 02:24

3 Answers3

4

You can store data for the time of auth session by utilising userdata field in auth cookie.

Code below is the LogOn action from AccountController in default MVC project:

 [HttpPost]
 public ActionResult LogOn(LogOnModel model, string returnUrl)
 {
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }
    // If we got this far, something failed, redisplay form
    return View(model);
}

You can replace:

FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

with:

string fullName = "User full name";

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, model.Email, DateTime.Now,
                DateTime.Now.AddDays(2), model.RememberMe, fullName);

string encTicket = FormsAuthentication.Encrypt(ticket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Expires = DateTime.Now.AddDays(2) });

If you want to store more data than you can pack in a normal string you will have to look into some sort of data serializer.

Then, you will have to implement something to parse serialized data when auth cookie is used.

Data is available through:

((FormsIdentity)User.Identity).Ticket.UserData;

Hope that helps

Edit: Also change DateTime.Now.AddDays(2) to whatever you want your auth session to remain valid.

LukeP
  • 10,422
  • 6
  • 29
  • 48
  • its not 'terrible' but storing data on the client side has shown to not be an optimal solution - especially after the recent POET vulnerability. – Adam Tuliper May 08 '11 at 06:26
1

Session state may be configured in a variety of ways to address the issues above. Specifically, if using in-process session state (wherein state is maintained within the same application domain/pool as the running application), simply increase the timeout to be equal-to or greater-than the form cookie timeout. If you wish to store session out-of-process (on a remote system or in a database), configure accordingly.
Here are a few resources:

Community
  • 1
  • 1
Bobby D
  • 2,129
  • 14
  • 21
  • Thank you, I like this approach, but I don't know why I can't make it work, I configure web.conf with .... but my session variables are still expiring – Santiago May 08 '11 at 03:28
  • Have you made any changes to the application pool that might be causing it to recycle? Also, certain other activities would cause the app pool to recycle (i.e. modifying the web.config, rebuilding your application, modifying files under the site more than 5(?) times). – Bobby D May 08 '11 at 03:33
  • Ahhh I'm working on the proyect so, rebuilding and publishing are recurrent jobs! Thanks!!!! – Santiago May 08 '11 at 04:04
0

Storing it in your auth cookie can be forged, and it can expire as well. How about this - if you can make your session and auth cookie expire at the same time, would that work? If so, I can provide that solution to you easily. The code below checks if the session is not available, if so you are redirected to the login page. Change login.aspx below to whatever your login is. Also upon login you MUST set Session["UniqueUserId"] to be some value (could be anything.. just needs to be set to something)

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            //Only access session state if it is available
            if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
            {
                //If we are authenticated AND we dont have a session here.. redirect to login page.
                HttpCookie authenticationCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
                if (authenticationCookie != null)
                {
                    FormsAuthenticationTicket authenticationTicket = FormsAuthentication.Decrypt(authenticationCookie.Value);
                    if (!authenticationTicket.Expired)
                    {
                        if (Session["UniqueUserId"] == null)
                        {
                            //This means for some reason the session expired before the authentication ticket. Force a login.
                            FormsAuthentication.SignOut();
                            Response.Redirect("Login.aspx", true);
                            return;
                        }
                    }
                }
            }
        }

Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71