I need to immediately invalidate and log out any other logged in sessions when a user changes their password, but allow the active session (who has just updated their password) to remain logged in.
To do this, I'm using the UpdateSecurityStampAsync(currentUser.Id);
method on the UserManager. All other sessions are successfully logged out, but the active session is also logged out despite the call to SignInAsync
after updating the security stamp.
The Identity configuration I'm using is as follows:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(0),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
CookieHttpOnly = true,
CookieSecure = CookieSecureOption.SameAsRequest,
SlidingExpiration = false,
ExpireTimeSpan = TimeSpan.FromMinutes(10)
});
The controller code snippet that is updating the password, updating the security stamp, and supposedly logging the current user back in is:
var updateResult = await _userManager.ChangePasswordAsync(currentUser.Id, form.CurrentPassword, form.NewPassword);
if (!updateResult.Succeeded)
{
//handle update failure
}
_signInManager.AuthenticationManager.SignOut();
//updating the security stamp invalidates all other sessions
await _userManager.UpdateSecurityStampAsync(currentUser.Id);
await _signInManager.SignInAsync(currentUser, false, false);
Running the code, the password is successfully updated and all sessions are logged out due to the security stamp being updated. But based on other examples I've seen (like this answer from Chris), the code above should refresh the auth cookie and keep the active user logged in.
I've tried different variations of the above code:
- Moving the sign out to after the security stamp update
- Removing the sign out altogether
- Using the synchronous
SignIn
extension method instead of the async one
all variations produce the same result: The user is forced to log back in after changing their password.
Is there a configuration error or something else that I've overlooked?
EDIT:
I've unintentionally fixed the problem by adding in the DefaultAuthenticationTypes
into the SignOut
call.
The relevant code now reads as:
//updating the security stamp invalidates all other sessions
await _userManager.UpdateSecurityStampAsync(currentUser.Id);
_signInManager.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
await _signInManager.SignInAsync(currentUser, false, false);
However, if anyone could explain why the Authentication type is important in this case?
Don't set validation interval to TimeSpan.FromMinutes(0), as that causes the sign in cookie to be issued immediately, set it to something like 1 second instead.