Invalidating active sessions after a password change?

2,630 views
Skip to first unread message

Dirley

unread,
Oct 2, 2012, 10:22:48 AM10/2/12
to django...@googlegroups.com
I've recently discovered this issue with my django based application.

When a users changes its password, its active sessions are not destroyed.
I mean, if a user is logged in two different places (or in two different
browsers) and changes its password on one place, the other session will still
be active.

I think this is an issue. If a user thinks his password has been stolen,
he'll naturally change his password in the hope that this action will revoke
the robber's undue access to his account. It's kinda "expected" that after a
password change, everyone with your old password will not be allowed to login.

But as far as I can tell, this has been the default behaviour for a long time
and no one ever bothered. So, am I missing something? Maybe my specific
setup (I changed my auth backend a little bit) is problematic?

- D

Tom Evans

unread,
Oct 2, 2012, 10:51:55 AM10/2/12
to django...@googlegroups.com
Sessions aren't tied to specific users, and so cannot easily be
invalidated like that. Personally, I wouldn't have the expectation
that changing my password would invalidate all my other sessions, but
perhaps a lay user would.

It is simple to add some middleware to ensure that sessions are linked
to user objects, and then you can insert any business logic you need
to take the appropriate action, eg to logout other sessions on a
password change.

Cheers

Tom

Cal Leeming [Simplicity Media Ltd]

unread,
Oct 2, 2012, 11:43:49 AM10/2/12
to django...@googlegroups.com
On Tue, Oct 2, 2012 at 3:51 PM, Tom Evans <teva...@googlemail.com> wrote:
On Tue, Oct 2, 2012 at 3:22 PM, Dirley <dirl...@gmail.com> wrote:
> I've recently discovered this issue with my django based application.
>
> When a users changes its password, its active sessions are not destroyed.
> I mean, if a user is logged in two different places (or in two different
> browsers) and changes its password on one place, the other session will still
> be active.

Actually, I disagree with this.

Say for example a user changes their password due to a security breach on their account.. if the session is not invalidated, the other user could carry on having access to their account for the maximum duration that the session allows.

The way we implemented this for one of our clients, was to cache the user password hash in the session, and re-check it against the database every X seconds. If it is different, the session is logged out.

The user which then triggers the password change will automatically have the cached session password hash updated, and thus the original session does not get terminated.
 
>
> I think this is an issue. If a user thinks his password has been stolen,
> he'll naturally change his password in the hope that this action will revoke
> the robber's undue access to his account. It's kinda "expected" that after a
> password change, everyone with your old password will not be allowed to login.
>
> But as far as I can tell, this has been the default behaviour for a long time
> and no one ever bothered. So, am I missing something? Maybe my specific
> setup (I changed my auth backend a little bit) is problematic?
>
> - D
>

Sessions aren't tied to specific users, and so cannot easily be
invalidated like that. Personally, I wouldn't have the expectation
that changing my password would invalidate all my other sessions, but
perhaps a lay user would.

It is simple to add some middleware to ensure that sessions are linked
to user objects, and then you can insert any business logic you need
to take the appropriate action, eg to logout other sessions on a
password change.

Cheers

Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.


Cal Leeming [Simplicity Media Ltd]

unread,
Oct 2, 2012, 11:45:01 AM10/2/12
to django...@googlegroups.com
Sorry, my previous reply looked like I was disagreeing with the OP, this is not the case.

I was disagreeing with this comment;

Sessions aren't tied to specific users, and so cannot easily be
invalidated like that. Personally, I wouldn't have the expectation
that changing my password would invalidate all my other sessions, but
perhaps a lay user would.

Google Mail in-line reply seems to be a bit fudged the last few days... :X

Cal

Tom Evans

unread,
Oct 2, 2012, 12:23:01 PM10/2/12
to django...@googlegroups.com
On Tue, Oct 2, 2012 at 4:43 PM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
>
>
> On Tue, Oct 2, 2012 at 3:51 PM, Tom Evans <teva...@googlemail.com> wrote:
>>
>> On Tue, Oct 2, 2012 at 3:22 PM, Dirley <dirl...@gmail.com> wrote:
>> > I've recently discovered this issue with my django based application.
>> >
>> > When a users changes its password, its active sessions are not
>> > destroyed.
>> > I mean, if a user is logged in two different places (or in two different
>> > browsers) and changes its password on one place, the other session will
>> > still
>> > be active.
>
>
> Actually, I disagree with this.
>
> Say for example a user changes their password due to a security breach on
> their account.. if the session is not invalidated, the other user could
> carry on having access to their account for the maximum duration that the
> session allows.
>
> The way we implemented this for one of our clients, was to cache the user
> password hash in the session, and re-check it against the database every X
> seconds. If it is different, the session is logged out.
>
> The user which then triggers the password change will automatically have the
> cached session password hash updated, and thus the original session does not
> get terminated.
>

I did not say that it was not a desired feature, I said that
*personally* I would not have that expectation; this may be due to me
fully understanding how such systems work and, as I indicated, a lay
person may think differently. Other large commercial systems, for
instance google apps, do not behave in this manner, so I'm not sure
where the expectation comes from - can anyone name a public facing
system that invalidates all other sessions on password change?

As a corollary, remember that django's authentication contrib package,
django.contrib.auth, is designed to be a *base* that all AAA schemes
can be built around. There are many schemes where a user may have many
passwords for a single account, should changing one of them invalidate
all their other sessions?

As I said in my original reply, these sorts of BI rules can trivially
be added on top of d.c.auth. I gave one such mechanism, Cal another.
Cal's solution is more about ensuring that only sessions that have the
current valid password hash are allowed, whilst mine is more about
tracking and invalidating specific sessions on a whim.

Cheers

Tom

Cal Leeming [Simplicity Media Ltd]

unread,
Oct 2, 2012, 2:50:37 PM10/2/12
to django...@googlegroups.com
That sure is a loaded comment, let's keep the dick size wars out of this yeah? :)
 
Other large commercial systems, for
instance google apps, do not behave in this manner, so I'm not sure
where the expectation comes from - can anyone name a public facing
system that invalidates all other sessions on password change?

Let's see.. Facebook?

--snip--
"Log out of other devices? To make sure your account's secure, we can log you out of any other computers and phones. You can log back in with your new password."
--snip

The only difference is that Facebook make it an optional feature that pops up immediately after you change the password.

The expectation comes from a simple logic. If I change my password, I want to think that my account is secure from anyone else that previously had it. 


As a corollary, remember that django's authentication contrib package,
django.contrib.auth, is designed to be a *base* that all AAA schemes
can be built around. There are many schemes where a user may have many
passwords for a single account, should changing one of them invalidate
all their other sessions?

That's a different question entirely, and comes down to a business logic choice, not a technical "one-fits-all".
 

As I said in my original reply, these sorts of BI rules can trivially
be added on top of d.c.auth. I gave one such mechanism, Cal another.
Cal's solution is more about ensuring that only sessions that have the
current valid password hash are allowed, whilst mine is more about
tracking and invalidating specific sessions on a whim. 

The solution I specified was the most simple approach possible, and could be integrated without too much fuss.

If you wanted more control, then yes tracking and invalidating individual sessions against your authentication model is the way forward.
Message has been deleted

Cal Leeming [Simplicity Media Ltd]

unread,
Oct 2, 2012, 6:30:47 PM10/2/12
to django...@googlegroups.com


On Tue, Oct 2, 2012 at 9:45 PM, Dennis Lee Bieber <wlf...@ix.netcom.com> wrote:
On Tue, 2 Oct 2012 17:23:01 +0100, Tom Evans <teva...@googlemail.com>
declaimed the following in gmane.comp.python.django.user:


>
> I did not say that it was not a desired feature, I said that
> *personally* I would not have that expectation; this may be due to me
> fully understanding how such systems work and, as I indicated, a lay
> person may think differently. Other large commercial systems, for
> instance google apps, do not behave in this manner, so I'm not sure
> where the expectation comes from - can anyone name a public facing
> system that invalidates all other sessions on password change? 
>

        I'd be more likely to expect any such system to, instead, limit an
account/user to /one/ active session... So the mere act of logging in a
second time should, itself, trigger the shutdown/invalidation of the
earlier session (possibly with a prompt first to give the person a
chance to locate the other session [if it is on the same machine]).
These systems probably also have inactivity time-outs on sessions too.

Sadly that breaks typical usage these days, especially since users will often login from multiple devices (tablets, PCs, phones etc).

Some of our clients have chosen to enforce single user login for licensing reasons, i.e. the customer pays more depending on the concurrent user count etc.

I'd say the best example of a good integration of this is Facebook... they have many problems, but login/session management definitely isn't one of them (imho).
 
--
        Wulfraed                 Dennis Lee Bieber         AF6VN
        wlf...@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

Tom Evans

unread,
Oct 3, 2012, 4:40:37 AM10/3/12
to django...@googlegroups.com
On Tue, Oct 2, 2012 at 7:50 PM, Cal Leeming [Simplicity Media Ltd]
<cal.l...@simplicitymedialtd.co.uk> wrote:
> On Tue, Oct 2, 2012 at 5:23 PM, Tom Evans <teva...@googlemail.com> wrote:
>> I did not say that it was not a desired feature, I said that
>> *personally* I would not have that expectation; this may be due to me
>> fully understanding how such systems work and, as I indicated, a lay
>> person may think differently.
>
>
> That sure is a loaded comment, let's keep the dick size wars out of this
> yeah? :)
>

It's not a loaded comment at all, this isn't a "dick size war".

>>
>> Other large commercial systems, for
>> instance google apps, do not behave in this manner, so I'm not sure
>> where the expectation comes from - can anyone name a public facing
>> system that invalidates all other sessions on password change?
>
>
> Let's see.. Facebook?
>
> --snip--
> "Log out of other devices? To make sure your account's secure, we can log
> you out of any other computers and phones. You can log back in with your new
> password."
> --snip
>
> The only difference is that Facebook make it an optional feature that pops
> up immediately after you change the password.

So not what your proposed solution allows, but instead session tracking...

>
> The expectation comes from a simple logic. If I change my password, I want
> to think that my account is secure from anyone else that previously had it.
>
>>
>> As a corollary, remember that django's authentication contrib package,
>> django.contrib.auth, is designed to be a *base* that all AAA schemes
>> can be built around. There are many schemes where a user may have many
>> passwords for a single account, should changing one of them invalidate
>> all their other sessions?
>
>
> That's a different question entirely, and comes down to a business logic
> choice, not a technical "one-fits-all".

This is point 1.

>
>>
>>
>> As I said in my original reply, these sorts of BI rules can trivially
>> be added on top of d.c.auth. I gave one such mechanism, Cal another.
>> Cal's solution is more about ensuring that only sessions that have the
>> current valid password hash are allowed, whilst mine is more about
>> tracking and invalidating specific sessions on a whim.
>
>
> The solution I specified was the most simple approach possible, and could be
> integrated without too much fuss.

See point 1. Your solution is the most simplistic approach to solve
this explicit use case, but implementing it in base would mean ruling
out many AAA schemes. Thanks for making my argument for me.


Tom

Cal Leeming [Simplicity Media Ltd]

unread,
Oct 3, 2012, 7:37:12 AM10/3/12
to django...@googlegroups.com
Yeah, this debate is borderline silly now.

OP, in a nut shell;

1) It is completely acceptable to revoke all other sessions after a password change
2) There are many ways to revoke sessions, pick one that is right for your use case.
3) Whether session revoking is enforced or optional is a choice for you.

Hope this helps!

Cal



Tom

Dirley

unread,
Oct 3, 2012, 10:17:11 AM10/3/12
to django...@googlegroups.com
So, thank you for the insights. I ended up with a solution that is a mix of
what you've proposed here.

Each time a user logs in, it's current *session validation token* is saved on
the session. It is easy to code this using the `user_logged_in` signal.

Then, I've changed the logic of the code that extracts the *authenticated user*
from the session. Now, it extracts the user and checks its token. If the token
doesn't match or is missing, the session is flushed (maybe it should be
deleted?) and the user is replaced by an instance of `AnonymousUser`.

The only thing not defined here is how to calculate the token. I'm currently
calculating it based on the user password, so when the user changes it's
password, the token is automatically refreshed. A more adequate approach would
be to save that token on an attribute of the user model or something, making it
optional to refresh the token or not (like Facebook does it).

An example of this implementation is available here:

http://pastebin.com/jASA4v6K

This is a quick and dirty solution. To use it, just call
`session_invalidation.setup` during the app boot (you can call it from inside
any installed app `models.py`). Note, though, that it does some things the
wrong way:

- It monekypatches `d.c.auth.get_user` to change it's logic and do the
token-checking magic. This is ok for a quick and dirty solution, but a more
sophisticated code would do it differently, maybe through middlewares.

- It calculates the token based on the user's current password. When the user
changes it's password, all it's active sessions are automatically
invalidated. Even the current one (the one where the password change was
done). I've managed to avoid this problem by calling
`session_invalidation.reset_session_validation_token` after changing the
password change, so the current session doesn't get invalidated.

That's it. Thank you for the clues.


- D

Альберт Тугушев

unread,
Jan 29, 2014, 12:12:46 PM1/29/14
to django...@googlegroups.com
Btw i wrote reusable application for this subject. Here is the link if it could help to someone: 
https://github.com/alikus/django-password-session

вторник, 2 октября 2012 г., 18:23:25 UTC+4 пользователь Dirley Rodrigues написал:
Reply all
Reply to author
Forward
0 new messages