0

UPDATE:

It is definitely not a bug in RC1. The cookie settings are working with the default UserManager and UserStore, so it must be something related to my UserManager/UserStore, I've overseen. I basically use the implementation here: https://github.com/jesblit/ASPNET5-FormAuthenticationLDAP

Original Post:

I have a problem with persistent logins. No matter how I configure the cookie, after 30 minutes, the User is automatically logged out (no matter how much the user interacts with the App).

I setup my App with:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCaching();
        services.AddSession(options => {
            options.IdleTimeout = TimeSpan.FromDays(1);
            options.CookieName = ".MySessionCookieName";
        });

        services.AddEntityFramework()
            .AddNpgsql()
            .AddDbContext<Model1>(options =>
                options.UseNpgsql(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<MinervaUser, MinervaRole>(options => {
            options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(1);
            options.Cookies.ApplicationCookie.SlidingExpiration = true;
            options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;

        })
            .AddUserStore<MinervaUserStore<MinervaUser>>()
            .AddRoleStore<MinervaRoleStore<MinervaRole>>()
            .AddUserManager<MinervaUserManager>();

        services.AddMvc();
    }

And:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");

            try
            {
                using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                    .CreateScope())
                {

                }
            }
            catch { }
        }
        app.UseIISPlatformHandler(options => { options.AuthenticationDescriptions.Clear(); options.AutomaticAuthentication = true; });
        app.UseSession();
        app.UseIdentity();
        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

The Login Action is:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {

                _logger.LogInformation(1, "User logged in.");
                return RedirectToLocal(returnUrl);
            }
...

I am using the default SignInManager. As said, the Expiration Timeouts I set in Startup.Configure and Startup.ConfigureServices have no effect at all. Login -> 30mins -> automatically logged out :(

What to do to extend this time period?

(btw: the custom User, UserManager, UserStore don't interfere with teh Cookie in any way, they "just" validate the credentials (what they're supposed to ;) ))

CodeNotFound
  • 22,153
  • 10
  • 68
  • 69
mcb
  • 194
  • 2
  • 8
  • It looks like you are using version RC1 or earlier. I don't think it's worth trying to figure out because it could be a Microsoft bug. I would update to RC2 and see what happens. – Clint B May 20 '16 at 16:17

1 Answers1

1

TL;DR: If you have a custom user manager, be sure to implement GetSecurityStampAsync, UpdateSecurityStampAsync and set SupportsUserSecurityStamp to true.


The solution to this is pretty simple (but I haven't found it anywhere in the docs). As the default implementation (Create new ASP MVC6 App...) works, I checked their DB tables and found the security stamp (which I didn't implement). According to the Answer to this question What is ASP.NET Identity's IUserSecurityStampStore<TUser> interface? this stamp is revalidated every 30 minutes, which surprisingly fits to my problem. So, all I did was extending my own UserManager with

public class MinervaUserManager:UserManager<MinervaUser> 
// Minerva being the name of the project
{
...
    public override bool SupportsUserSecurityStamp
    {
        get
        {
            return true;
        }
    }
   public override async Task<string> GetSecurityStampAsync(MinervaUser user)
    {
        // Todo: Implement something useful here!
        return "Token";
    }

    public override async Task<IdentityResult> UpdateSecurityStampAsync(MinervaUser user)
    {
        // Todo: Implement something useful here!
        return IdentityResult.Success;
    }

These dummies always return the same SecurityStamp and "Success" on every Update. This is as secure as not having the SecurityStamps at all bit prevents the logout.

mcb
  • 194
  • 2
  • 8