6

When a user is logged into a web-based application in multiple tabs, and changes their password, should it automatically log them out of the other tabs? The use case is an account is compromised, the attacker logs in, the user also logs in and changes their password, however, since the attacker was already logged in, they are still granted access until they log out.

This seems to require storing the password bcrypt hash in session, and then every request check the session bcrypt hash against the bcrypt hash in the database. Is there an alternative approach?

  • 1
    Why not just close all open sessions and be done with it? – user36976 Jul 16 '14 at 16:53
  • How do you close all open sessions by a certain user id? Also, this would log the current user out, which is a bad experience. – Justin Jul 16 '14 at 16:55
  • This is a old question, but I am curious if this is implemented out of box in Identity Apps like Ping Identity, Oracle Access Manager, WSO2 Identity Server, Okta etc.? – Saqib Ali Feb 15 '18 at 6:49
3

TL;DR: How do you know it's not the attacker who is changing the password? In that case, you would log out the legitimate user. Or a user might want to routinely change their password (a good practice), but not if they have to login again on all devices every time. I would only log all other sessions out if (1) the user clicks the button "log all other sessions out", or (2) the user uses the forgot-password feature (thereby confirming their email address, or something else which provides stronger proof that it's them than a password).


When to log all other sessions out?

There are a few cases in which a user's password gets changed:

  • User notices or suspects a compromise, and changes their password
  • Attacker just gained access to an account and changes the user's password
  • User forgot their password
  • Attacker compromised user's email account and uses the forgot-password feature
  • User routinely changes their password, either because they think it improves security or because of a policy

In each case, you would want to make a different choice, but it's impossible to distinguish between the legitimate user and an attacker. Since you can hardly ask the user to confirm their password when using the forgot-password feature, we have to either disregard the case where an attacker compromised a user's email account, or use another method of confirming the user's identity (e.g. a recent purchase, an SMS verification code, a security question[1], etc.).

Since we do not know who is changing the password when it is changed from the interface, I think it's not unreasonable to leave other sessions active. In that case, other sessions should be terminated when a user does a password reset (after they confirmed the password reset link, not whenever anyone enters their email into the form, because that could be abused). Imagine the scenario in which both are logged in and know the password: both will try to change the password (assuming they know of each other) and it's just luck who gets there first. But once the password reset feature has been used successfully by someone, you have a higher confidence that this is the legitimate user.

Another consideration is whether to have a separate interface for logging other sessions out: you could have a button for "Log out all other sesssions", perhaps next to a list of all other sessions and past logins. I would recommend having this, since a user can check what is going on when something strange happens to their account. An attacker will be unable to hide their presence.

How to manage the sessions?

Ideally, you should have a list of active sessions for any account, as well as a history of logins. The history of logins should date back a certain amount of time, not a certain number of logins: if only the last X logins are shown, an attacker will be sure to look in the account history, spoof the user agent and country/state/city using VPN, and do X logins to push his own login out of memory.

This can be managed in a database, where each login session is registered. Using a expires column, you can purge sessions which have expired. And a session should get removed upon log out of course. Note that this is separate from login logging: having logged out, it should still be visible that someone logged into the account using <device> from <location> on <datetime>. The only thing to remove (or the boolean to toggle) is that the session is active.

Doing some trickery with bcrypt-hashed passwords, as described in the question, is not needed (and definitely not recommended!). The session state should be independent from a user's password by design: otherwise session tokens have a meaning which could be guessed if you make some tiny mistake, even if the attacker doesn't really know the password. Or conversely, an attacker could learn the password through offline brute-force, when all they ever obtained was a session token.

Generally speaking, there should be a list of sessions with at least two columns: session token and the user's unique identifier. The session token should be random bytes, optionally hashed (in order to not leak data from a compromised or weak PRNG). The user's unique identifier should be stable: no display name, and preferably not a username. Use a single-use unique identifier, such as an auto-incrementing column in MariaDB/MySQL. Usually a third column is added, expiration time, but this is not strictly necessary. I would highly recommend it, though, even if you set it to multiple years.

For each request, the database can be checked for the presence of the session token. If a user does something that invalidates other sessions, it's a simple matter to inactivate (or delete) the user's other sessions.


[1] Do not use security questions as a replacement for a password. The only reason I dare mention it, is because it can be an addition: when the user confirmed a secret code (or link) sent to their email account, or when they proved that they know their password, you could use it to get a little more certainty that it's the real user and not an attacker.

2

When a user is logged into a web-based application in multiple tabs, and changes their password should it automatically log them out of the other tabs?

If a user is logged in using a cookie based mechanism then logging out of one tab will log the user out of all tabs. If they only change their password, then as they will still be logged into the session on the current tab, they will remain logged in on the other tabs. Unless you have implemented something fancy such as the multiple session functionality of Gmail, then each tab on the same browser is the same session.

The use case is an account is compromised, the attacker logs in, the user also logs in and changes their password, however, since the attacker was already logged in, they are still granted access until they log out.

Yes this can happen on some systems such as Forms Authentication in ASP.NET.

The default Forms Authentication SignOut method does not update anything server side, allowing a captured auth token to be continued to be used or a session with a changed password will continue to be valid:-

Calling the SignOut method only removes the forms authentication cookie. The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie.


This seems to require storing the password bcrypt hash in session, and then every request check the session bcrypt hash against the bcrypt hash in the database. Is there an alternative approach?

Yes, you could either track sessions server side. For example, assigning a cryptographically secure string as the Session ID which is set as a cookie value and is looked up in the database for each request.

Another approach is to store a hash of the password last changed date/time as part of the auth cookie which is checked on every request.

Obviously these have performance hits compared to a Session ID that can be checked independently of any database connectivity, but it would be possible to cache these values as long as they are expired appropriately. In the case of the Session ID being stored server side, you would also have to have the appropriate mechanism (again, with overhead) to keep sessions alive if a sliding expiration was required.

1

When a user logs out or changes their password, it should revoke their session token, which is usually a hash that identifies them, like fc2904-92385-4jf9

The server should know that the particular session token is no longer good, and so if you have the application open in other windows, and you attempt to continue browsing, the server should reject all of your requests due to the token expiry.

  • Sure log out works fine, but changing their password keeps them logged in. – Justin Jul 16 '14 at 17:01
  • "their session token, which is usually a hash that identifies them" It can probably be implemented in a way that it is secure, but having a session token with a meaning feels very wrong to me. I'd not advise this, ever. The only exception would be where you hash your random bits as to not leak randomness from a faulty CSPRNG (see: Dual EC DRBG). – Luc Jan 29 '18 at 18:11
  • "the server should reject all of your requests due to the token expiry." An expired token should obviously be rejected, but that is a separate issue from whether to log out other sessions when changing one's password. This does not answer the question. – Luc Jan 29 '18 at 18:13
0

User changes his password for different reasons not only because his account is compromised. So terminating other opened sessions subsequently after changing password is just bad from user experience perspective.

However to achieve a perfect user protection in this specific case while preserving the user convenience, a better approach would be prompting user for the password before any next action he takes in his current session.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.