ASP.NET Universal Providers - Session not shared between instances as expected
I've searched around and this seems like a no-brainer. I am using the ASP.NET Universal Providers (1.1 of nuget package). However, session is clearly not being shared between the instances because after logging in, as I click around to links I sometimes am re-directed to the login page and sometimes am authorized to access the content.
Below are the relevent parts of my web.config:
<connectionStrings>
<add name="ApplicationServices"
connectionString="Data Source=xxxxxxx;Initial Catalog=xxxxxxxxxx;Persist Security Info=True;User ID=xxxxxxxxx;Password=xxxxxxxx;Encrypt=true;MultipleActiveResultSets=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<machineKey validation="HMACSHA256" />
<membership defaultProvider="DefaultMembershipProvider" hashAlgorithmType="HMACSHA256">
<providers>
<clear />
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile defaultProvider="DefaultProfileProvider">
<providers>
<clear />
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="true" defaultProvider="DefaultRoleProvider">
<providers>
<clear />
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</roleManager>
<sessionState mode="Custom" customProvider="DefaultSessionProvider">
<providers>
<clear />
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</sessionState>
</system.web>
The only significant deviation with my configuration and the boilerplate configurations described out there is the machineKey and membership hashAlgorithmType configuration. These are necessary to ensure the password hash used by Azure to authenticate a user's credentials match the hash used when creating the user accounts via the ASP.NET Configuration utility.
All the examples about using the universal providers are so straight-forward and never mention any "gotcha" issues to be aware of so I can't think where to even begin looking.
Ideas?
Thanks
Well, I'm sure caching would work. However, there are additional fees associated with the caching approach which we don't want to incur (this is for a non-profit with very limited funds). They are already paying for a SQL Azure database and it should be relatively trivial to get session managed in the database.
For the above reasons, I reject your answer. Correct me if I'm wrong.
Can anyone actually help me get the universal providers working? They are supposed to be fully supported by Microsoft after all.
Thanks
EDIT: I just noticed here: https://www.windowsazure.com/en-us/pricing/details/#caching that, in fact, the caching preview does not have additional costs. I'll likely give it a try. Thanks for directing me to look into that Brent.
So I tried the caching preview feature Brent directed me to, and I get the same behavior!
Here is my new sessionState configuration:
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
<providers>
<clear />
<add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="default" />
</providers>
</sessionState>
My cloud service configuration:
<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="xxxxx" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*" schemaVersion="2012-05.1.7">
<Role name="xx">
<Instances count="2" />
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=xxxx" />
<Setting name="Microsoft.WindowsAzure.Plugins.Caching.NamedCaches" value="{"caches":[{"name":"default","policy":{"eviction":{"type":0},"expiration":{"defaultTTL":20,"isExpirable":true,"type":2},"serverNotification":{"isEnabled":false}},"secondaries":0}]}" />
<Setting name="Microsoft.WindowsAzure.Plugins.Caching.Loglevel" value="" />
<Setting name="Microsoft.WindowsAzure.Plugins.Caching.CacheSizePercentage" value="30" />
<Setting name="Microsoft.WindowsAzure.Plugins.Caching.ConfigStoreConnectionString" value="DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=xxxx" />
</ConfigurationSettings>
</Role>
</ServiceConfiguration>
And in my service definition file I now have the following elements:
<Imports>
<Import moduleName="Diagnostics" />
<Import moduleName="Caching" />
</Imports>
<LocalResources>
<LocalStorage name="Microsoft.WindowsAzure.Plugins.Caching.FileStore" sizeInMB="1000" cleanOnRoleRecycle="false" />
</LocalResources>
Seriously, this is odd. Session state works fine when deploying to a single instance, but as soon as I increase the instance count to 2+, I am routinely randomly redirected to the login page.
At this point I have to believe this is unrelated to the specific session provider I'm using? But if so, what else could it be?
I'm glad you realized that the caching preview does not incur additional costs.
However, the machine key may be the issue. I seem to recall that the machine key is generated dynamically by the host VM so this could be part of the issue. If you can get your membership provider to use another key, this may address the problem you're experiencing.
Session provider in ASP.NET Universal providers works fine in azure hosted services, however it doesn't work in compute emulator in case you have multiple instances.
This is same even if you do not use this provider and use SQL Server directly for sharing session. In compute emulator it will not work, however, it works perfectly fine once hosted in Azure.
If this post answers your question, please mark it as an answer. If this post is helpful to you, then vote it as helpful.
TechyFreak |
Mobile Development Resources
I'm actually encountering this same exact issue. I wrote about it before and now after some more testing, the issue still persists. I followed this guide and configured the site to use AppFabricCacheSessionStoreProvider, but my site throws the user back to login form almost all the time. Sometime the user can use the site and click the links for few minutes before the need to login again but often it takes less than five clicks and the user is back starting at the login form. My cloud service is running on two instances.
Here's how I've configured the sessionState:
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
<providers>
<add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="default" />
</providers>
</sessionState>
And here's the dataCacheClients configuration:
<dataCacheClients>
<dataCacheClient name="default">
<hosts>
<host name="host.cache.windows.net" cachePort="22233" />
</hosts>
<securityProperties mode="Message">
<messageSecurity
authorizationInfo="key">
</messageSecurity>
</securityProperties>
</dataCacheClient>
</dataCacheClients>
I have a feeling that the problem is caused by the following setting in my Web.config:
<system.web>
<machineKey validation="HMACSHA256" />
But this is required because without it, the cloud services use the wrong validation algorithm.
Here's how I've configured the providers:
<profile defaultProvider="DefaultProfileProvider">
<providers>
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="Sql_Azure" applicationName="/"/>
</providers>
</profile>
<membership defaultProvider="DefaultMembershipProvider">
<providers>
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="Sql_Azure" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/"/>
</providers>
</membership>
<roleManager enabled="true" defaultProvider="DefaultRoleProvider" cacheRolesInCookie="true" cookieName=".asproles" cookieTimeout="20" cookieSlidingExpiration="true" cookieProtection="All" createPersistentCookie="false">
<providers>
<add connectionStringName="Sql_Azure" applicationName="/" name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</providers>
</roleManager>
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
<providers>
<add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="default" />
</providers>
</sessionState>
Any ideas? This issue is driving me nuts.Hi guys
When working with multiple instances, azure automatically adds a machinekey for you in web.config
This is so session can work on an application across multiple servers.
Consider this:
You drop (delete) your existing staging environment, then re-create it, then swap VIPs.
In this scenario you could have different machine keys between staging environment and production environment. At this point, the "stored" session object will not be correct because the hash would be different, therefore redirecting to login again.
Another is to drop your production environment and re-create, the same will occur, the session hash is stored in cache and then becomes incorrect.
|