Share session across sub-domains in Azure for ASP.NET app

Sometimes you may want to share session across sub-domains in Azure. You could find many articles and posts for this question, like this, but it only applies to on-premises environment because:

a) The InstallSqlState.sql doesn’t work for Azure SQL Database
b) It requires a custom http module to modify the application name to generate a same session id across domains. But Azure Web App is managed environment that doesn’t allow to install custom http module.

In this post, I will show you how to overcome the 2 issues above and share session in Azure successfully.

Prerequisites

1, Prepare 2 web apps, app 1 for creating session and app 2 for reading session in Azure. And configure custom domain for them, for example, subdomain1.devchat.live and subdomain2.devchat.live.

Note, custom domain is required because based on our test, it seems Azure blocks to share session  for Web App default domain, azurewebsites.net.

Steps

1, Add the settings like below in web config on both apps(ensure the settings are exactly same on both apps, including machineKey):

    <machineKey

        decryptionKey="EDCDA6DF458176504BBCC720A4E29348E252E652591179E2"

        validationKey="CC482ED6B5D3569819B3C8F07AC3FA855B2FED7F0130F55D8405597C796457A2F5162D35C69B61F257DB5EFE6BC4F6CEBDD23A4118C4519F55185CB5EB3DFE61"/>

    <sessionState mode="SQLServer" sqlConnectionString="Server=tcp:<yourAzureServerEndpoint>,1433;Persist Security Info=False;User ID=<yoursqlname>;Password=<yoursqlpassword>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" />

    <httpCookies domain=".devchat.live" />

<machineKey> is used to decrypt and validate Session State data. You can refer to https://blogs.msdn.microsoft.com/amb/2012/07/31/easiest-way-to-generate-machinekey/ to generate a new one.

<sesstionState> indicates the app uses sql server as session store. Use your own connection string.

<httpCookies> set cookie scope to root domain, so session cookie can be shared across subdomains. “devchat.live” is my test domain, replace with yours.

2, In Azure SQL, create a database named “ASPState”. Then run the attached sql script at the bottom. It’s modified based on on-premises InstallSqlState.sql(which usually can be found in <system drive>:\Windows\Microsoft.NET\Framework\<.NETFrameworkversion> ) to work on Azure.

3, In global.asax in both web apps, add the following code in Application_Start method:

FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime",

                                                BindingFlags.Static | BindingFlags.NonPublic);

HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null);

FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId",

            BindingFlags.Instance | BindingFlags.NonPublic);

appNameInfo.SetValue(theRuntime, "myApplicationName"); //replace with you actual name

The code is to change application name, so these 2 apps will use same session id.

4, Publish to Azure

Now it should works. But in InstallSqlState.sql of on-premises environment, it contains a sql job that executes stored procedure “DeleteExpiredSessions” to clean the expired sessions. The problem is Azure SQL Database doesn’t support sql job. So we have to find a way to clear expired session periodically to prevent the database from becoming extremely large.

In Azure, you can use WebJobs or Function to accomplish this. Considering we already have web app, so WebJobs is recommended as it’s shipped with Web App and will not cause extra cost. Please refer to Create a scheduled WebJob for more information. Note: you need to enable Always On for web app to keep the WebJob active.

Here I provide a sample PowerShell script that executes “DeleteExpiredSessions” stored procedure  :

$SqlConnection = New-Object System.Data.SqlClient.SqlConnection

$SqlConnection.ConnectionString = "server=tcp:<yourAzureServerEndpoint>,1433;Initial Catalog=ASPState;User ID=<yourUserName>;Password=<yourpassword>;"

$SqlCmd = New-Object System.Data.SqlClient.SqlCommand

$SqlCmd.CommandText = "DeleteExpiredSessions"

$SqlCmd.Connection = $SqlConnection

$SqlCmd.CommandType=[System.Data.CommandType]::StoredProcedure

$SqlConnection.Open()

$SqlCmd.ExecuteNonQuery() | Out-Null

$SqlConnection.Close()

Summary

To share session across subdomains in Azure for ASP.NET, basically you need to:

1, Ensure the 2 web apps are using sessionID

2, Store session in external store, like Azure SQL in this post.

If you encounter any problems, welcome to our chat channel for assistance: http://aka.ms/devchat

 

InstallSqlState.sql:

InstallSqlStateOnAzure

Leave a Reply

Your email address will not be published. Required fields are marked *