ASP.Net Core, Cookie Expiration and Mysterious Logout on IIS

Working with cookie expirations on Asp.Net Core may be a bit confusing. Although settings are simple, varierity of settings can mislead you.

IsPersistent

First setting I want to mention is IsPersistent. When it is set to true, It will be kept even if browser closed (persistent cookie). As opposite when it is set to false, cookie will be cleared when the browser is closed. (session cookie)

ExpireTimeSpan

This settings helps us to set expiration date of the ticket stored in cookie. For example, the setting below will make the ticket in the cookie invalid after 15 mins.

options.ExpireTimeSpan = TimeSpan.FromMinutes(15);

SlidingExpiration

Sometimes we want to extend expire timespan if client uses the application actively. With this setting, It will be reset expiration time if client make a request after more than half of the expiretimespan interval passed.

If a browser send a request with a cookie that has expired ticket, server will ignore it.

ExpiresUtc

ExpiresUtc setting helps you to set an absolute expiration to cookie. This settings overrides ExpireTimeSpan setting value. This setting will also ignore SlidingExpirationSetting.

ExpiresUtc = DateTime.UtcNow.AddMinutes(20)

Another important point is that when you set ExpiresUtc, If you don’t set IsPersistent setting, cookie will be created as session cookie.

Mysterious Logout on IIS Server

Despite all of these settings you may experience that users are loging out after some minutes eg 20mins. Most probably you will not catch this behaviour on local while developing your application. It is related with some settings on IIS.

To fix this behaviour, first you need to go to advanced settings of application pool.  You will see a setting called “Idle Time-out (minutes)” and must set as 0. Its default value is 20mins. It means that if no new request comes for 20 mins, worker process will be shut down.

When an app restarted or worker process restarted and If the keys related with authentication kept in memory;

Cookie based authentication tokens will be invalid and users will need to log in again.

So to keep keys persistent, we need to set one more setting on advanced settings of Application Pool; Load User Profile must be set to True. So keys will be stored in a folder on operation system. (%LOCALAPPDATA%/ASP.NET/DataProtection-Keys)

Sources: https://docs.microsoft.com/en-au/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-3.0#absolute-cookie-expiration

 

Sharing sessions between subdomains – Asp.Net Mvc Apps on IIS

Sometimes, you need to share sessions between different apps on different sub domains. There are some steps to achieve this behaviour and I will try to explain them today.

If we want apps to behave like single app on different subdomains, firstly they must use same cookies. With shared cookies, users won’t have to logged in for each app. They will be able to logged in / out only once for all apps.  In order to share cookies we need to add a setting under system.web section in webconfig for cookies:

<httpCookies domain=".yourmaindomain.com"/>

With this setting, any subdomain under yourmaindomain.com use the same cookies. But there is one more step here, all apps have to same machinekey setting on webconfig. Machinekey attribute is used while encrypting and decrypting the data for the webapplication in ASP.NET.

Before move further, Lets create two websites on our web server.

iis create web site

After creating two websites, for one, select MachineKey feature and click Generate Keys. Copy Validation Key and Decryption Key. Then open other app’s Machine Key feature and paste copied values to related fields.

These values will be pasted to a web config attribute too.

<machineKey validationKey="XXXXX" decryptionKey="XXXXX" validation="SHA1" decryption="AES" />

This attribute will be under system.web section in webconfig.

These changes helps us to use shared cookies without any problem. But to achieve our goal completely, we need to do one more thing. We have to store session state in database, so all applications will share same session data. By adding setting below to web config and editing to connection string, all session data will be shared.

<sessionState 
            mode="SQLServer"
            sqlConnectionString="data source=127.0.0.1;user id=username;password=strongpassword"
            cookieless="false" 
            timeout="20"/>