I have an issue with the ASP.NET Identity provider. I started with the default template that comes with Visual Studio 2019, targeting .NET 4.7.2 WebForms.
On the change password page, the Identity provider doesn't seem to be updating the .AspNet.ApplicationCookie
to reflect the new SecurityStamp
. I can see in Fiddler that ASP.NET is sending a 302 to redirect back to the Manage.aspx page and it is sending an auth cookie, that presumably should reflect the new SecurityStamp
that results from the password change, except that it doesn't. So the user is immediately logged out of the application after a password or 2FA change, since I have validateInterval
set to TimeSpan.Zero
. If I set it to another value, the user's cookie becomes invalid after that value, regardless of the actual age the cookie is supposed to have.
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.ExpireTimeSpan = TimeSpan.FromDays(14),
.SlidingExpiration = True,
.Provider = New CookieAuthenticationProvider() With {
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
validateInterval:=TimeSpan.Zero,
regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))},
.LoginPath = New PathString("/Account/Login")})
And here is the relevant code in the change password page:
Protected Sub ChangePassword_Click(sender As Object, e As EventArgs)
If IsValid Then
Dim manager = Context.GetOwinContext().GetUserManager(Of ApplicationUserManager)()
Dim signInManager = Context.GetOwinContext().Get(Of ApplicationSignInManager)()
Dim result As IdentityResult = manager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text)
If result.Succeeded Then
Dim userInfo = manager.FindById(User.Identity.GetUserId())
signInManager.SignIn(userInfo, isPersistent:=False, rememberBrowser:=False)
Response.Redirect("~/Profile/Manage?m=ChangePwdSuccess")
Else
AddErrors(result)
End If
End If
End Sub
Turns out you need to log the user out and then log them back in:
Protected Sub ChangePassword_Click(sender As Object, e As EventArgs)
If IsValid Then
Dim userManager = Context.GetOwinContext().GetUserManager(Of ApplicationUserManager)()
Dim signInManager = Context.GetOwinContext().Get(Of ApplicationSignInManager)()
Dim authenticateResult = Context.GetOwinContext().Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie).GetAwaiter.GetResult()
Dim accountChangeResult As IdentityResult = userManager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text)
If accountChangeResult.Succeeded Then
Context.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie)
Dim userInfo = userManager.FindById(User.Identity.GetUserId())
signInManager.SignIn(userInfo, isPersistent:=authenticateResult.Properties.IsPersistent, rememberBrowser:=False)
Response.Redirect("~/Profile/Manage?m=ChangePwdSuccess")
Else
AddErrors(accountChangeResult)
End If
End If
End Sub