简体   繁体   中英

Cookie Authentication Early Expiration

Issue

In my ASP.NET MVC Core 2.0 application I have setup to use the cookie authentication scheme without using Identity as we have our own backend authentication storage and api.

The authentication and authorization works perfectly every time.

However, no matter what the login/session expires after approximately 30 minutes. You can see that we are setting the timeout to 120 minutes for both authentication cookie and session cookie.

Application information:

  • Platform: .Net 4.7.x (Windows)
  • Framework: Asp.Net Core 2.x
  • IIS used as a proxy server

Any help or input on how to solve this would be welcome

Code

Update: Replaced services.AddMemoryCache() with services.AddDistributedRedisCache(..) - testing to see how this works

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedRedisCache(options =>
        {
            options.Configuration = "localhost";
            options.InstanceName = "CoreTestInstance";
        });

    services.AddAuthentication("CookieAuthenticationScheme")
        .AddCookie("CookieAuthenticationScheme", options => 
        {
            options.Cookie.Name = authSettings.Name;
            options.Cookie.HttpOnly = false;
            options.Cookie.Expiration = TimeSpan.FromMinutes(120);
            options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
            options.AccessDeniedPath = new PathString("/Errors/StatusCodeErrors/401");
            options.LoginPath = "/Account/Login";
        });
        // services.AddMemoryCache();
        services.AddSession(options =>
        {
            options.Cookie.Name = sessSettings.Name;
            options.Cookie.HttpOnly = false;
            options.IdleTimeout = TimeSpan.FromMinutes(120);
        });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Errors/Default");
    }
    app.UseStatusCodePagesWithRedirects("/Errors/StatusCodeErrors/{0}");
    app.UseStaticFiles();
    app.UseAuthentication();
    app.UseSession();
    app.UseMvc();
}

AccountController.cs

[HttpPost("Login")]
public async Task<IActionResult> Login(AccountModel model)
{
    var claims = new List<Claim>();
    claims.Add(new Claim(ClaimTypes.Name, model.UserName));
    claims.Add(new Claim(ClaimTypes.Role, "Administrator", ClaimValueTypes.String, model.UserName));

    var identity = new ClaimsIdentity(claims, "login");
    var principal = new ClaimsPrincipal(identity);
    await HttpContext.SignInAsync("CookieAuthenticationScheme", principal);
}

You're using in-memory sessions, which are tied to the process. That process in IIS is your App Pool. By default, the App Pool recycles automatically after a period of time. When it recycles, it takes your sessions with it.

Use a persistent session store : SQL Server, Redis, etc. (Sessions use distributed cache, so the way you set up persistent sessions is to setup a persistent distributed cache store.)

Thanks to Chris Pratt to starting me in the right direction. Moving to Redis helped with performance and distributed caching is the right way to go.

However, Redis did not solve my problem, the app still timed out after 90 minutes regardless of my settings.

Since we use IIS I ended up having to change settings in the AppPool to finally get the session to honor my timeout instead of the AppPool's.

  • For the AppPool, click on the Advanced Settings and make the following changes:
    • Section: Process Model
      • Idle Time-out (minutes) = 0 (disables the timeout so that the application pool will never shut down due to being idle)
      • Idle Time-out Action = Suspend (A suspended worker process remains alive but is paged-out to disk, reducing the system resources it consumes)
    • Section: Recycling
      • Regular Time Interval (minutes) = 0 (setting to 0 means the apppool will not recycle)

Note: The above settings should not affect other applications unless you have a great deal many applications running on the same server. I suggest you research the settings in detail before using them to ensure they will work for you.

Finally, I ran several tests with various settings (we store them in appsettings.json) for timeout from 2 mins, 10 mins, 1 hour and finally 2 hours and all worked as required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM