ASP.NET Core Website Expires After 30 Minutes

I have an ASP.NET Core MVC application hosted on Azure sites where I implemented Session and Identity. My problem: after 30 minutes I exit the system. It doesn't matter if I have been active in the last 30 minutes or not.

While doing some searches, I found that the problem is with the SecurityStamp file, here . I tried to implement this by doing the following:

Here is my prompting UserManager with a security stamp:

public class UserManager : UserManager<Login> { public UserManager( IUserStore<Login> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<Login> passwordHasher, IEnumerable<IUserValidator<Login>> userValidators, IEnumerable<IPasswordValidator<Login>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<Login>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) { // noop } public override bool SupportsUserSecurityStamp => true; public override async Task<string> GetSecurityStampAsync(Login login) { return await Task.FromResult("MyToken"); } public override async Task<IdentityResult> UpdateSecurityStampAsync(Login login) { return await Task.FromResult(IdentityResult.Success); } } 

Here is my ConfigureServices method on Startup.cs:

 public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddApplicationInsightsTelemetry(Configuration); services.AddSingleton(_ => Configuration); services.AddSingleton<IUserStore<Login>, UserStore>(); services.AddSingleton<IRoleStore<Role>, RoleStore>(); services.AddIdentity<Login, Role>(o => { o.Password.RequireDigit = false; o.Password.RequireLowercase = false; o.Password.RequireUppercase = false; o.Password.RequiredLength = 6; o.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(365); o.Cookies.ApplicationCookie.SlidingExpiration = true; o.Cookies.ApplicationCookie.AutomaticAuthenticate = true; }) .AddUserStore<UserStore>() .AddUserManager<UserManager>() .AddRoleStore<RoleStore>() .AddRoleManager<RoleManager>() .AddDefaultTokenProviders(); services.AddScoped<SignInManager<Login>, SignInManager<Login>>(); services.AddScoped<UserManager<Login>, UserManager<Login>>(); services.Configure<AuthorizationOptions>(options => { options.AddPolicy("Admin", policy => policy.Requirements.Add(new AdminRoleRequirement(new RoleRepo(Configuration)))); options.AddPolicy("SuperUser", policy => policy.Requirements.Add(new SuperUserRoleRequirement(new RoleRepo(Configuration)))); options.AddPolicy("DataIntegrity", policy => policy.Requirements.Add(new DataIntegrityRoleRequirement(new RoleRepo(Configuration)))); }); services.Configure<FormOptions>(x => x.ValueCountLimit = 4096); services.AddScoped<IPasswordHasher<Login>, PasswordHasher>(); services.AddDistributedMemoryCache(); services.AddSession(); services.AddMvc(); // repos InjectRepos(services); // services InjectServices(services); } 

And finally, here is my Configure method on Startup.cs:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseApplicationInsightsRequestTelemetry(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/home/error"); } app.UseStatusCodePages(); app.UseStaticFiles(); app.UseSession(); app.UseIdentity(); app.UseMiddleware(typeof (ErrorHandlingMiddleware)); app.UseMiddleware(typeof (RequestLogMiddleware)); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } 

What happened to my implementation here?

UPDATE . What a second ... I noticed that my UserManager does not inherit from any interfaces for security stuff, is that what you need?

+7
source share
3 answers

This is simply because you need to enable and configure data protection . Cookie and session settings look correct. What is happening for you right now is that whenever the application is restarted or the server load balancing on another server or a new deployment, etc., it creates a new data protection key in memory, so your user session keys are invalid. Therefore, all you have to do is add the following to Startup.cs:

  services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"D:\writable\temp\directory\")) .SetDefaultKeyLifetime(TimeSpan.FromDays(14)); 

Use the documentation to find out how to properly configure this and the various options for where to save the data protection key (file system, Redis, registry, etc.). You can think of the data protection key as replacing the web.config machine key in asp.net.

Since you mentioned that you are using Azure, you can use this package Microsoft.AspNetCore.DataProtection.AzureStorage to save the key and save it. So you can use this example of using Azure storage .

+5
source

Do you participate in IIS? If so, there might be something wrong with your code, but your application pool may be recycled (check the additional parameters in the application pool). When this happens, your binary is unloaded from memory and replaced with a new one; does it change its PID?

+1
source

See a similar problem here and an error report here .

In short, this is a bug in ASP.NET Core 2.1, if you implement your own IUserStore but do not implement IUserSecurityStampStore, the user logs out after 30 minutes, even if the cookies have not expired.

A quick fix increases the security stamp check to a fairly safe value, for example, like this:

 services.Configure<SecurityStampValidatorOptions>(o => o.ValidationInterval = TimeSpan.FromHours(10)); 
0
source

Source: https://habr.com/ru/post/1263684/


All Articles