So, you’ve set the timeout value for forms authentication to a fairly large value, yet checking the “remember me” check box on the Login control still does not persist your users’ authentication, even after a fairly short period of inactivity.
<system.web> ... <authentication mode="Forms"> <forms timeout="10080"/> </authentication> ... </system.web>
Don’t spend hours trying to figure out why this, seemingly, basic functionality doesn’t perform as it should. The solution to this problem is very simple, albeit somewhat obscure.
Encryption is the Key
To make the “remember me” check box actually obey your users when they check it, you need to ensure that a static machine key is added to your website’s web.config file. That’s it! Really.
<system.web> ... <machineKey validationKey="xxxxxxxxx" decryptionKey="xxx" validation="SHA1" decryption="AES"/> ... </system.web>
Generate Random Keys
Generate your own keys by using one of the machineKey generator websites available. After using a generator, copy and paste the machineKey element inside the system.web element of your web.config.
The “remember me” option for authentication should start working as expected.
Why this Works
When a user authenticates on an ASP.NET website with forms authentication enabled, an authentication ticket is generated for that user. This ticket is then stored inside a cookie in the user’s browser. The cookie’s purpose is to allow the forms authentication system to recognize subsequent requests by the same user as valid/authenticated.
Of course, this functionality works without issue even before the solution above. When a user leaves the “remember me” box unchecked, a session cookie is stored in their browser. Checking that box, sends a persistent cookie back to the browser instead. This persistent cookie is set to expire based on the timeout value mentioned earlier (i.e. it expires approximately timeout minutes from the current date/time). The persistent cookie is also created without issue. A quick look at your cookies during a test should prove this.
So, if the persistent cookie is getting created properly, why are users being forced to login again after only short periods of inactivity? Well, the authentication ticket is encrypted before being sent to the browser as a cookie. This is done to secure the details of the ticket and prevent tampering. However, the ticket must be decrypted by the forms authentication system on each request that follows.
When the ASP.NET process recycles, the website’s validation and decryption keys may be randomly re-generated. In fact, the default behavior is to auto-generated these keys per application. If the keys are changed, those tickets cannot be decrypted. When the forms authentication system fails to decrypt a ticket from the user’s cookie, it sends them along to the login page for validation. No amount of checking the “remember me” box will help this situation; specifying your own keys in web.config will.
Causes of Process Recycling
There are a number of causes for the ASP.NET process getting recycled. Here just a few.
- IIS determines certain conditions were met
- any change in the bin directory of the website
- changes to the physical path of the virtual application or website
- a sub-directory of the website is deleted
- changes to Global.asax, web.config, or machine.config
- policy changes
- the count threshold of re-compilations is exceeded (numRecompilesBeforeAppRestart on the compilation element)
If your website is hosted on a shared server, odds are the process for your application will get recycled more often than on a dedicated server. Hosts set the thresholds for recycling pretty low for shared hosing servers to account for poor programming.
I almost always recommend that one of the first things a developer does with a new ASP.NET website is generate a random machineKey and add to the web.config. This will likely save you many headaches in the future. By the way, this step is absolutely necessary for Web farms/gardens.