I have a requirement to eliminate multiple active sessions from being allowed on our site.
It is my understanding that to do this you can manipulate the validateInterval parameter of the OnValidateIdentity property of the CookieAuthenticationProvider as below:
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(0), //Changed from default of 30 minutes
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
I changed the default value from 30 minutes to 0 for testing and it works as anticipated. If I log in to a second browser the next action taken in the first browser redirects me to the login page.
I also allow users to change their password whenever they want (after login). With the validateInterval property at zero, the user is logged out immediately after submitting a password change. They then log back in with the new password and are able to use the site as normal.
If I change the validateInterval parameter value to say 10 seconds, the user is allowed to continue the current session after submitting a password change for 10 seconds and then is redirected to the login page.
Inside the ChangePassword action of the ManageController class the default code that runs after a successful password change is this:
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
}
I thought that the line SignInManager.SignInAsync would keep the user's session going even through a password change (from Logout User From all Browser When Password is changed), but it seems to be controlled additionally by the validateInterval parameter.
If I wanted to allow a user to change their password during an authenticated session without forcing then to login again, could I do this with ASP.NET Identity and still control multiple active sessions? Is there a better way to control multiple active sessions without changing the validateInterval parameter (from Prevent multiple logins)?
Thank you for your help. To clarify, if this behavior is by design, I am fine with it. I just want to understand what is going on so I can defend the behavior to my boss if needed.
Edit:
I failed to mention that I also update the security stamp directly prior to the sign in via SignInManager in the Login action.
Doing what you're doing does not prevent multiple active sessions. I'm also assuming by "sessions" you're talking about multiple authentications by the same user account. Multiple active sessions, in the truest sense, is an entirely different discussion. That said, the cookie that's set to maintain the user's "authenticated" state is client-specific. If I log on from my desktop computer and from my mobile device, or even from both Chrome and Internet Explorer on the same computer, those are all different cookies, unaffected by other cookies that may have been set on other devices or browsers.
The only way you could truly prevent this is to somehow mark the user as "logged in" server-side (i.e. a column on your user table for example). Then, before authenticating them anywhere else (basically in your sign in post action), you would check their user account for this flag. If it's already set, then you would refuse to log them in again until they first log out on the original device/browser. Obviously, your log out action would have to then unset this flag, so they would be allowed to log in again elsewhere.