Few days ago I have decided to upgrade my web app from asp.net core 1.1 to core 2.0. Everything seems to work fine after minor changes, except authentication does not persist longer than 20-30 minutes.
We can take the default example from Visual Studio because I experience the same problem in my own webapp and in "ASP.NET Core Web Application" -> .NET Framework 4.6.1 + ASP.NET Core 2.0 + MVC + Individual User Accounts.
Configuration is default and should be users logged in for 14 days:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
...
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
...
}
The PROBLEM is that user only stays logged in for 20-30 minutes. When user logs in ("Remember me" is selected) you can navigate through pages, and even reopen the browser, user stays logged in. Thus it seems authentication cookie is working. However, after 20-30 minutes user is logged out automatically, or should I say cookie expires (I do not know what happens). You can login again, and the game starts all over again.
I have tried setting Application cookie expiration, but this does not solve the problem:
services.ConfigureApplicationCookie(options => {
options.ExpireTimeSpan = TimeSpan.FromDays(1); // Just shortens cookie expiration time, but still logs out users after 20-30 minutes.
});
Since it takes 20-30 minutes, it looks like default session timeout:
services.AddSession(options =>
{
options.Cookie.Expiration = TimeSpan.FromDays(1); // This throws an error "Expiration cannot be set for the cookie defined by SessionOptions"
options.IdleTimeout = TimeSpan.FromDays(1); // This changes session sliding expiration time...
});
The same implementation worked fine in ASP.NET Core 1.1.
Ok then I have spammed different forums regarding this :) And here are my discoveries. Original https://github.com/aspnet/Identity/issues/1389
It seems there was a big gap in my understanding about how does this all work. I also found that I have lied a little. So to finish up for other as stupid as me.
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.Configure<SecurityStampValidatorOptions>(options => options.ValidationInterval = TimeSpan.FromSeconds(10));
services.AddAuthentication()
.Services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
});
According my understanding this works like this:
the check if user is logged happens ~every 10 seconds, depending on requests ratio. Server checks security stamps upon every request to the server options.ValidationInterval = TimeSpan.FromSeconds(10))
.
cookie is valid at minimum for 30 minutes options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
, but can be extended with options.SlidingExpiration = true;
if page is refreshed or navigated.
important! do not be too "smart" like me and do no run _userManager.UpdateSecurityStampAsync(user);
just after successful login. Because this updates security stamp and next validation validation will fail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With