Migrating ASP.NET MVC applications to .NET Core: Session issue with multiple sites on different ports.

by Mauricio Rojas, on Dec 5, 2020 9:48:40 AM

Migrating a couple of WebSites from ASP.NET MVC to .NET Core, we found an interesting issue.

NOTE: this issue was not caused by .NET Core, it is just an issue. Some users say this used to work when they only used IE but I do not have IE8 to verify that.

Ok. So after migration, there was a need to deploy these two applications on the same server. Let’s say:

  • http://localhost:90 and http://localhost:91

However when the QA team started testing the application, weird things happened.

We were able to determine that the problem was caused because the two applications were sharing the same Session ID. But why?

When in ASP.NET the session is set, it is maintained using an cookie called .AspNetCore.Session. Cookies are isolated by domain. So for http://localhost1 and http://locahost2 the browser will keep different cookies. But there is no cookie port isolation:

According to RFC 6265 :

Cookies do not provide isolation by port. If a cookie is readable by a service running on one port, the cookie is also readable by a service running on another port of the same server. If a cookie is writable by a service on one port, the cookie is also writable by a service running on another port of the same server. For this reason, servers SHOULD NOT both run mutually distrusting services on different ports of the same host and use cookies to store security sensitive information.

 

​But our client wanted that kind of deployment… What can we do.

Well luckily the Asp.Net core is fairly customizable. So we a possible solution is to have different cookies per website.

For example for http://localhost:5000 we can have a cookie .AspNetcore.Session5000 and for http://localhost:5001 we can have a cookie .AspNetcore.Session5001.

That sounda nice. But how can we get the actual address that is being used? 

I not that the information is somewhere in the DI, but the session is configured inside the ConfigureServices method and at that point in time how can we access the service provider which is created later?

After some research we found great post  from Andrew Lock about getting the address information and another one about getting using the services. Thanks Andrew!!!!

So putting those two together we came up with this code:

/// <summary>
/// This class was created so the IService provider can be used to obtain information
/// before setting the session options
/// For more information see:
/// Access services inside ConfigureServices using IConfigureOptions in ASP.NET Core
/// https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/
/// </summary>

public class ConfigureSessionOptions : Microsoft.Extensions.Options.IConfigureOptions<SessionOptions> {

private readonly IServiceScopeFactory _serviceScopeFactory;

public ConfigureSessionOptions(IServiceScopeFactory serviceScopeFactory) {

 _serviceScopeFactory = serviceScopeFactory;
}


public void Configure(SessionOptions options) {

  using (var scope = _serviceScopeFactory.CreateScope()) {

    var provider = scope.ServiceProvider;
    using (var server = provider.GetRequiredService<IServer>()) {

          var addressFeature = server.Features.Get<Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature>();
          var firstAddress = addressFeature.Addresses.FirstOrDefault();
          if (firstAddress!= null) {
             if (Uri.TryCreate(firstAddress, UriKind.RelativeOrAbsolute, out var firstAddressUri)) {
                               options.Cookie.Name += firstAddressUri.Port;
                               }
                          
             }
      }
  }
 }
}

And I just needed to add this code inside my ConfigureServices section:

 

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDistributedMemoryCache();
            services.AddSession();
            services.AddSingleton<Microsoft.Extensions.Options.IConfigureOptions<SessionOptions>, ConfigureSessionOptions>();
            services.AddControllersWithViews();
        }

 

Ok.  Now you can see the code running:

and now I have port independent SessionCookies 😊

So as you can see things are great in .NET Core. So move all those old Asp.Net MVC website to .Net Core. Got a question? Just ask. We will be glad to help.

 

Topics:application migrationC#asp.net.netcore

Comments

Subscribe to Mobilize.Net Blog

FREE CODE ANALYSIS TOOL