IsPersistent not working - Cookie only valid for current session
Asked Answered
C

3

8

I have an ASP.NET MVC 5 application using ASP.NET Identity 2.1.0 for user authentication.
Everything worked fine in the past, but now I found out that persisting user sessions does not work anymore. I can not tell what change broke this, but it worked when I implemented Identity (converted the application from SimpleMembership) and this is my logic I have at the moment:

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, 
                                     model.RememberMe, shouldLockout: true);

SignInManager is my ApplicationSignInManager based on SignInManager<ApplicationUser, int> and model.RememberMe is true.

And my setup:

app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = ApplicationCookieIdentityValidator.OnValidateIdentity(
                    validateInterval: TimeSpan.FromMinutes(0),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
    });
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

Everything works fine, except persisting the user sessions. I checked the cookies returned by my server and the .AspNet.ApplicationCookie is allways returned as "valid for current session" instead of some date in the future. So when I close and reopen the browser I need to log in again...

Does anybody have an idea why this is not working (anymore)?

P.S.: I have overriden SignInAsync in my ApplicationSignInManager because I do some custom logic there, but I even checked with the debugger and for the following call:

await base.SignInAsync(user, isPersistent, rememberBrowser);

isPersistent is true, so it should create a persisten cookie.

Chon answered 8/9, 2014 at 19:26 Comment(2)
I suspect validateInterval: TimeSpan.FromMinutes(0) can cause this. Because on every request it regenerates cookie and sets a new one. Try setting validateInterval to something more than 0 and see if that works.Macadam
@trailmax: Thanks, that was it. Was that changes with V 2.1? Because it definitely worked in the beginning (with V 2.0). Anyhow: Post this as an answer and I will accept it. I now need to find away around this, as I need (because of SSO) validation on every request.Chon
M
8

This is a known bug in Identity and by looking on this answer it is not very new.

When cookie is regenerated on every request, "IsPersisted" flag is not set, when, even when it was set in the original cookie.

To work around this, you will need to implement your own version of cookie validator that will set the flag as is should.

I think I've got the solution for you, but I have not compiled or tested it - just merely a general direction of where you need to go. See this gist for full code.
This is just a SecurityStampValidator code taken from decompiler. I've added lines 91-96. Basically I take "IsPersistent" flag from the previous cookie and add it to the new cookie, when it is created. That was not done in non-modified version.

And then in your Auth.Config you do:

Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = MySecurityStampValidator.OnValidateIdentity(
                    validateInterval: TimeSpan.FromMinutes(0),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }

Beware though, when new version is out, check if this was fixed, so you can remove the dirty fix. This issue is reported to be fixed, but shortly after v2.1 was out.

Macadam answered 8/9, 2014 at 21:26 Comment(6)
Thank you VERY much. As I already have my own validator (see ApplicationCookieIdentityValidator in my code) I just needed to add your changes there too -> working!Chon
@ChrFin Yes, I noticed the name is different from the standard. Glad it helps!Macadam
nice code! Looks like it is missing using Microsoft.Owin.Security; to access the AuthenticationProperties type thoughRecite
This works for me #31947082Rebekahrebekkah
@Sergey a year? more like 4 years since my answer. Identity 2 is not getting developed anymore, what do you expect?Macadam
This code is almost perfect!, Just in the case that any other developer out there is having issues with the Two Factor Authentication setup, just change TimeSpan.FromMinutes(0) to TimeSpan.FromMinutes(5) as stated in the official helpInjudicious
S
1

Updating both AspNet.Identity.Core and AspNet.Identity.Owin to 2.2.1 should resolve this issue.

Scenarist answered 25/9, 2016 at 11:33 Comment(2)
after updating it still has same problem and even default template for asp.mvc for Identity core has the same issue.Ariosto
#31947082Rebekahrebekkah
V
-1

In order to keep a user loggedin on browser close in Mvc Indentity. The below code is what worked for me in Startup.Auth.cs class.

app.UseCookieAuthentication(new CookieAuthenticationOptions
                    { 
                        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                        SlidingExpiration = true,
                        CookieHttpOnly = false,
                        LoginPath = new PathString("/Account/Login"),

                        Provider = new CookieAuthenticationProvider
                        {  
                            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                            validateInterval: TimeSpan.FromMinutes(30),

                                regenerateIdentity: (manager, user) => 
                                user.GenerateUserIdentityAsync(manager)),

                            OnResponseSignIn = context => {
                                context.Properties.IsPersistent = true; };
                            } 
        }
Venator answered 27/3, 2019 at 9:58 Comment(1)
FYI, you should not be using CookieHttpOnly = false here. It should be set to true or omitted (since true is the default). An HTTP only cookie cannot be accessed by JavaScript in the browser. But with this code, malicious JavaScript from a cross site scripting attack could yank your user's auth cookie.Bernoulli

© 2022 - 2024 — McMap. All rights reserved.