ChrFin ChrFin - 2 months ago 17
C# Question

IsPersistent not working - Cookie only valid for current session

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.

Answer

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.

Comments