sorcery icon indicating copy to clipboard operation
sorcery copied to clipboard

"Remember Me" functionality doesn't work when users access my app from 2 separate browsers

Open RogerPodacter opened this issue 13 years ago • 27 comments

I've run into a pretty annoying behavior in which "remember me" doesn't work across browsers. Here's how to reproduce it:

  1. Log in on Browser A (remember me = true)
  2. Log in on B (remember me = true)
  3. Quit browser A
  4. Re-open browser A

You are now logged out of the application on browser A. Instead, you should remain logged in on browser A until you click "log out"

RogerPodacter avatar Jan 16 '12 21:01 RogerPodacter

Isn't that normal since you are still logged in browser B?

alexcp avatar Jan 16 '12 21:01 alexcp

"Remember me" means "keep me logged in on this browser until I click log out". I.e., the behavior of "remember me" shouldn't depend on what I've done on another browser / computer somewhere.

I feel very strongly that this is the correct behavior – this is how Gmail, Facebook, and Twitter all behave. In fact, I can't think of a single famous web application that has the current sorcery behavior. (Also, AuthLogic's "remember me" behaves in my preferred manner as well)

RogerPodacter avatar Jan 16 '12 21:01 RogerPodacter

I think that's because sorcery saves a new remember_me_token to the DB on every "remember me" request, regardless on browser. This makes the remember_me_token in other browser cookies revoked.

The solution that comes to my mind right now is to create a DB "session" record for every login from every browser, with expiration date, instead of the single token per user record. When the user cookie is sent, the token is looked up in the sessions table, and the user id is retrieved and auto-logged in.

NoamB avatar Jan 16 '12 22:01 NoamB

I think the solution is to save a new remember_me token only when the use changes his password, not when he logs in with a "remember me" request.

I.e.:

  • Every user has a remember_me token
  • Checking "remember me" when you log in tells the server to add this token to your cookie
  • If you log into multiple browsers with "remember me", each browser gets a cookie with the same remember_me token
  • When the user changes his password, reset his remember_me token as well (and put the new token in his cookie if the old token was there)

This is what authlogic and most websites do.

RogerPodacter avatar Jan 17 '12 01:01 RogerPodacter

If you don't also keep expiration info on each browser, than the expiration will take effect from the time of the first browser, even if the last browser asked for "remember me" just a minute ago (unless you put a really big expiration time and then it won't matter).

Also, when using the same token until you change password, you increase the window of getting your token read by an attacker.

I found this link: http://stackoverflow.com/questions/2594960/best-practice-to-implement-secure-remember-me

and it made me think it might be a good security measure to generate a new token on each login via cookie. Will make the attack window even smaller. Of course, to make it work across browsers means keeping a record per browser.

NoamB avatar Jan 17 '12 06:01 NoamB

Ok, so we have httpOnly turned ON (prevents javascript from reading it), the cookie is signed (prevents cookie tampering), and let's say we don't use SSL. So an attacker can now only steal your token by listening to your network traffic.

If we switch remember_me token on every login, even if an attacker gets your token by listening, it is already void.

NoamB avatar Jan 17 '12 07:01 NoamB

If you don't also keep expiration info on each browser, than the expiration will take effect from the time of the first browser, even if the last browser asked for "remember me" just a minute ago (unless you put a really big expiration time and then it won't matter).

Right, the correct behavior is to have a large (and in fact functionally infinite) expiration time. If the user checks "remember me" he shouldn't be logged until he clicks "log out". This is how almost all websites work; e.g., I think I've been using the same Gmail "remember me" token on my iPhone for over a year

If we switch remember_me token on every login, even if an attacker gets your token by listening, it is already void.

Right; this is the current behavior, and while it's more secure, it's also more inconvenient for the user (/ not what they expect). (And if security is your #1 concern, you should just disable "remember me" functionality entirely – by implementing "remember me" a developer is saying "I want to sacrifice security for convenience because this isn't a banking website" or whatever)

and it made me think it might be a good security measure to generate a new token on each login via cookie. Will make the attack window even smaller. Of course, to make it work across browsers means keeping a record per browser.

I don't see how having one token per browser is better (or functionally different at all, actually) from having one global token. As you say, the big security issue is someone sniffing any valid remember_me token. So who cares whether the user's token is "cat" on Firefox and "dog" on Chrome; you can still own him by sniffing his traffic from EITHER browser and grabbing EITHER token, no?

RogerPodacter avatar Jan 17 '12 17:01 RogerPodacter

No no, what I meant was, the token the attacker is sniffing right now, is already obsolete, because when the user sends me his token, I give him a new one on the spot. The attacker could also sniff for the new token sent from the server, but the window to use it will be very short if it is constantly replaced. This is a very secure remember me, though a bit taxing on the DB. Such feature will have to be managed per browser since each browser holds a different token at each time.

But that was just thinking out loud...

regarding Gmail, I'm actually logged out once a month on my browser, so it's not 9999 years expiration.

I do agree the whole feature is insecure by nature... I guess it will not be less secure than it is now with your suggestion.

However, I would like your opinion (anyone) on the ultra secure remember me feature.

NoamB avatar Jan 17 '12 17:01 NoamB

No no, what I meant was, the token the attacker is sniffing right now, is already obsolete, because when the user sends me his token, I give him a new one on the spot. The attacker could also sniff for the new token sent from the server, but the window to use it will be very short if it is constantly replaced. This is a very secure remember me, though a bit taxing on the DB.

Ah – let me see if I understand:

  1. Client logs in with "remember me"
  2. Server gives him a remember me token (say it's "dog"), and a browser identification token (say it's "pepsi")
  3. On next request, client sends server token "dog" (and his browser identification token "pepsi"). Server sees that it's the same client and he's logged in with "remember me" and the request succeeds
  4. Server now gives the client a new token ("cat")
  5. Client makes another request with token "cat" (and the same browser identification token "pepsi"). Server sees that it's the same client and he's logged in with "remember me" and the request succeeds
  6. Server gives the client a new token again! ("house")
  7. If the attacker had sniffed "cat" before, it's useless. The only way an attacker can own the client is by sniffing the new token the server sends down BEFORE the client uses it in a subsequent request

This does seem like a more secure strategy if you're not using SSL. But if the server REALLY cares about security, it must implement SSL anyway, which kills the advantages of this approach – I mean, without SSL the client can still get SUPER-DUPER-owned by simply having his password sniffed, and the only way to defend against that is with SSL.

Either way, I think your proposed strategy could be a future feature, but that in the meantime you should change the behavior to reset the remember_me token on password change instead of log in since, though it is less secure, it's what the user expects / wants (and it's a much simpler change).

RogerPodacter avatar Jan 17 '12 18:01 RogerPodacter

On second thought, if I needed secure login I would just use SSL... :-)

NoamB avatar Jan 17 '12 18:01 NoamB

Yes, your algo description is correct, and I've (finally) reached the conclusion that SSL is the answer...

Alright, it will be fixed when I get around to it. Pull requests are also welcome, as always ;-)

NoamB avatar Jan 17 '12 18:01 NoamB

I feel like the current approach and what people write on the internetz is too model-centric. I used authlogic previously and it was even more confusing by introducing an additional UserSession class. Why not simply use Rails session for the remember me functionality? This is an ideal application for the session construct. They've done all the hard work for you. As always it's best to use a database-backed session, especially if you are already using authentication (hopefully with SSL). In your before_filter you check last_login_at with your remember-me period to decide what to do. After that you can execute require_login and everything works as always. You don't even need adding a remember_me field to your model. It can be "volatile" in the session, but resurrected from login to login. If you find ActiveRecord session store slow, then you can use Cache or Redis store.

timofeytt avatar Feb 26 '12 00:02 timofeytt

A more appropriate term would be server-based session :)

timofeytt avatar Feb 26 '12 01:02 timofeytt

*server-backed

timofeytt avatar Feb 26 '12 01:02 timofeytt

I looked at the code yesterday and noticed that session_timeout is doing something similar, but unfortunately the current implementation doesn't allow me to leverage it to implement a session-based remember_me and inactivity timeout at the same time. When you have config.session_timeout_from_last_action = false it doesn't track last_activity in the session.

timofeytt avatar Feb 26 '12 19:02 timofeytt

Any progress with this? I'd also like to see Sorcery provide better support for users who wish to be remembered in multiple browsers (on multiple devices). That seems like a pretty standard feature these days.

mokolabs avatar Mar 13 '13 19:03 mokolabs

Bump, this would be ideal like @mokolabs mentioned when you have users accessing from multiple devices it would be nice for remember_me to work for multiple sessions

ghost avatar Oct 17 '13 23:10 ghost

@arnvald Any updates on this issue? I'll implement a workaround in my own project if not, but don't want to duplicate effort if it's coming soon...

bfischer1121 avatar Aug 01 '14 20:08 bfischer1121

Hi @bfischer1121, I want to do it in August, but I can't promise if I manage to.

arnvald avatar Aug 02 '14 09:08 arnvald

@arnvald Let me know if you need any help. I would love to see this get added to Sorcery.

mokolabs avatar Aug 02 '14 09:08 mokolabs

@NoamB @arnvald Any news? I will need this functionality soon for a client's project. If you're not already working on it I would be glad to do it myself, following your guidelines. Let me know, thanks!

MartinodF avatar Nov 19 '14 11:11 MartinodF

This seems like it would be useful functionality. Has there been any further progress since this discussion?

stevehill1981 avatar Nov 25 '14 16:11 stevehill1981

@MartinodF @stephenorr @arnvald I would also be down for helping out.

mokolabs avatar Nov 26 '14 12:11 mokolabs

@arnvald I'd like to help out in any way possible to get this out the door. Thanks for the great gem.

bfischer1121 avatar Feb 26 '15 13:02 bfischer1121

@bfischer1121 @mokolabs @MartinodF

if any of you wants to take this task, I'll be very happy to help. A few months ago Devise introduced some solution, I think it's worth checking it to see if it works well and if it's easy to implement in Sorcery.

I’ve created a Gitter room for Sorcery: https://gitter.im/NoamB/sorcery - feel free to ask me any questions there.

arnvald avatar Mar 03 '15 16:03 arnvald

To all waiting for some progress on this: I have implemented support for persisting the login token as a configuration option (default behavior remains unchanged). See my pull request here with full details: #690. Please use and test in your apps to see if it solves your use case.

rubiety avatar Apr 28 '15 23:04 rubiety

Here's a little background on the pull request from @rubiety.

We've been using sorcery for a few years on Graffletopia, and the lack of support for multiple "remember me" browser sessions has always annoyed me.

So I thought this would be a good opportunity for us to contribute back to the sorcery project by having @rubiety devote some time to fixing this issue.

Please let me know what you think!

mokolabs avatar Apr 28 '15 23:04 mokolabs