Cookie expires or session timeout too soon

raklos picture raklos · Oct 8, 2014 · Viewed 11.7k times · Source

I have code like this which is run when a user is authorized:

 FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                 1,
                 email,
                 DateTime.Now,
                 DateTime.Now.AddMinutes(120),
                 true,
                 userData);

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

I then redirect to a controller/Action that has the Authrize attribute:

 [Authorize]
    public class ProductsController : Controller
    {

I have the following in web.config:

 <authentication mode="Forms">
      <forms loginUrl="~/Home/Unauthorized" timeout="2880" />
    </authentication>
    <sessionState timeout="120"></sessionState>

However users are complaining of session timing out or redirecting Home/Unauthorized after a couple of mins of inactivity.

what could be causing this, what else should i check?

Answer

Tommy picture Tommy · Oct 13, 2014

A couple of thoughts before I go into a possible solution of why your logins are expiring. First, the FormsAuthentication cookie and SessionState are two different things completely. You can have one or the other, or both or neither. As a result, the timeouts for these two items are also not related.

The FormsAuthentication cookie is an encrypted cookie that contains some basic information such as the user name and an expiration value. The .NET application uses this cookie once a user has authenticated to know if the user is authorized for certain resources.

What controls the encryption and decryption of the FormsAuthentication cookie is the MachineKey for that web application on IIS. The MachineKey is a set of keys used to encrypt and decrypt the cookie. By default, a web application on IIS is set to AutoGenerate the machine key. What this means is that when an application starts, a random machine key is generated. If an application recycles, you get a new machine key. Additionally, if you are hosting on a shared provider, the web host will typically have your application load balanced, meaning hosted by more than one server. Each one of those servers will auto generate a machine key.

If your web application is on a load balanced scenario, then each machine in the web farm cannot decrypt the other's encrypted cookie. This will give the appearance of "being logged out". The example of this is logging in on web server A, then a subsequent request goes to web server B. Web server B does not share a machine key with web server A and cannot decrypt the cookie, sending the user back to the login page.

The solution is to define the MachineKey section in your web.config so each instance of IIS will use the same keys as well as if the application pool recycles, you still have the same machine key.

Here would be an example machine key (use the .NET 2.0 version) that you could place in your web.config

<system.web>
  <machineKey validationKey="EBC1EF196CAC273717C9C96D69D8EF314793FCE2DBB98B261D0C7677C8C7760A3483DDE3B631BC42F7B98B4B13EFB17B97A122056862A92B4E7581F15F4B3551" 
    decryptionKey="5740E6E6A968C76C82BB465275E8C6C9CE08E698CE59A60B0BEB2AA2DA1B9AB3" 
    validation="SHA1" decryption="AES" /> 
</system.web>

Additional thoughts are that your expiration in your web.config (2880) and what you are actually setting the expiration to be (120) do not match. You may want them both to match.