ASP.NET Universal Providers - Session not shared between instances as expected

Answered ASP.NET Universal Providers - Session not shared between instances as expected

  • Thursday, August 16, 2012 8:24 PM
     
      Has Code

    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


    • Edited by bojingo Thursday, August 16, 2012 8:25 PM
    •  

All Replies

  • Thursday, August 16, 2012 8:56 PM
    Moderator
     
     
    personally, I'd just use the caching preview feature of the 1.7 SDK for session handling and be done with it. It creates a shared in-memory cache using the memory available in your guest VM's.
    • Proposed As Answer by Carlos Sardo Thursday, August 16, 2012 9:26 PM
    • Unproposed As Answer by bojingo Friday, August 17, 2012 12:59 PM
    •  
  • Friday, August 17, 2012 12:59 PM
     
     

    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.
    • Edited by bojingo Friday, August 17, 2012 1:15 PM
    •  
  • Friday, August 17, 2012 5:53 PM
     
      Has Code

    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="{&quot;caches&quot;:[{&quot;name&quot;:&quot;default&quot;,&quot;policy&quot;:{&quot;eviction&quot;:{&quot;type&quot;:0},&quot;expiration&quot;:{&quot;defaultTTL&quot;:20,&quot;isExpirable&quot;:true,&quot;type&quot;:2},&quot;serverNotification&quot;:{&quot;isEnabled&quot;:false}},&quot;secondaries&quot;: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?


    • Edited by bojingo Friday, August 17, 2012 5:53 PM
    •  
  • Friday, August 17, 2012 11:19 PM
    Moderator
     
     Answered

    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.

  • Tuesday, August 21, 2012 3:47 AM
     
     

    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

  • Wednesday, September 26, 2012 2:41 PM
     
      Has Code

    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.
  • Tuesday, October 02, 2012 11:01 AM
     
     

    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.