Search code examples
asp.net-coreasp.net-identity

Random ASP.NET Core Identity Logouts in production


I have an ASP.NET Core MVC web application that uses Identity to handle user account Authentication and Authorization. When running the app on my local IIS express everything was working properly. After deploying the app to a shared web server I started to notice that the logged-in user accounts would get logged out at seemingly random intervals. Through experimentation, I was able to determine that the log-outs were occurring whether the account was active or idle. They were occuring at no recuring time interval and completely unrelated to any expiry time that I set on my cookies. The logouts were occuring on every view in the web app so I couldn't pin the issue to any particular controller. Also I use the same Database for the published and the local testing version of the app and therefore the same user accounts. I anyone has an idea where to start looking for a solution it would be greatly appreciated.


Solution

  • I posted this question because there is a great answer that 90% solves the issue Here however of the multiple forums that I have been scouring over the last few days there are none with an accepted answer. I am posting this answer to address this. The underlying cause of the issue is that IIS application pool is being reset or recyling and on a shared host with multiple applications using it this can be happening fairly frequently. As is suggested in the above link Data Protection has to be used to persist the keys if IIS application pool recycles. Here is the code offered in the original answer.

    services.AddDataProtection()
                .PersistKeysToFileSystem(new System.IO.DirectoryInfo("SOME WHERE IN STORAGE"))
                //.ProtectKeysWithCertificate(new X509Certificate2());
                .SetDefaultKeyLifetime(TimeSpan.FromDays(90));
    

    This code is to be added in ConfigureServices in Startup.cs As my application is being hosted on a shared server using .PersistKeysToFileSystem was not an option so instead I persisted the keys using DbContext like this:

                services.AddDataProtection().PersistKeysToDbContext<MyKeysContext>()
                .SetDefaultKeyLifetime(TimeSpan.FromDays(90));
    

    Based on This article here I build MyKeysContext as follows.

        // Add a DbContext to store your Database Keys
    services.AddDbContext<MyKeysContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("MyKeysConnection")));
    

    In ConfigureServices in Startup.cs and then created a class called MyKeysContext as follows:

    using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    using WebApp1.Data;
    namespace WebApp1
    {
     public class MyKeysContext : DbContext, IDataProtectionKeyContext
     {
        // A recommended constructor overload when using EF Core 
        // with dependency injection.
            public MyKeysContext(DbContextOptions<MyKeysContext> options) 
            : base(options) { }
    
            // This maps to the table that stores keys.
         public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
        }
    }
    

    I created the database on my Host this will probably be different so I have omitted this step. then I applied the migrations to the database like this.

    Add-Migration AddDataProtectionKeys -Context MyKeysContext 
    Update-Database -Context MyKeysContext