5

I've implemented the Improved Persistent Login Cookie Best Practice for a "remember me" option.

This works fine when requests are in sequence (traditional page loading). In this case you are sure that the next request will have the same series identifier and the token that was last sent by the server.

But in the case of AJAX requests, where multiple requests are coming in parallel from the same browser, the first request will result in the generation of a new token number. But the other requests will not have this newly generated token number and they'll we denied access considering it as a theft.

How do we get around this problem?

smhg
  • 2,159
  • 19
  • 26
Dhiraj
  • 550
  • 6
  • 14

3 Answers3

1

Based on the proposed solution on the aforementioned Drupal thread (https://www.drupal.org/node/327263#comment-3428038), I'm wondering if we cannot have a simpler algorithm.

Instead of storing "old" replaced tokens in a short lived caching table, why not use the current users session?

1. User logs in with PL cookie
If series & token are in PL table:
  2. User session is populated with the last valid token
  3. new token is given to client
  4. user is logged in
If series key is in PL table, but token is not:
  2. check if current user session still holds the latest replaced token
  If found:
    3. user is logged in.  No new token is provided since one was generated in the first request.
  If not found:
    3. Assume keys are stolen - series is destroyed

This algorithm won't work in load balanced scenarios though, when the session state is not properly replicated to all nodes though!

bluegaspode
  • 108
  • 6
  • If the first request has not gone back to the browser, isn't the session id unknown for the other requests as well? – Thor May 18 '17 at 09:56
  • yes, unfortunately you are right :( We moved to a local in-memory cache for upgraded tokens (which keep valid for about 5 seconds). I.e. step two is replaced by this cache. – bluegaspode May 19 '17 at 16:27
0

I think you confused remember me with CSRF (Cross Site Request Forgery) protection tokens. CSRF tokens protect application by disabling a possibility of unauthenticated "functionality execution". And they do that by issuing nondeducible token to each response, and verifying it upon reciving a request.

Remember me feature is a feature which allows user to login, even if the original session was long gone. Without the need of providing his username/password again. You should set your remember me token, once or once on every successful login. Not in every response. You do not set session cookie in every response why would you set a remeber me token ?

damiankolasa
  • 1,508
  • 9
  • 8
  • I had put the link to the wrong question. Sorry for the confusion. I updated the link now. – Dhiraj Nov 28 '12 at 21:30
  • Still the same question holds why would you want to issue new series on EVERY request ? And not on login ? – damiankolasa Nov 29 '12 at 05:54
  • @fatfreddy If we generate a remember me token upon login only, then if it gets stolen and somebody sends a request with this token, then he has access to the system and there is no way to detect if the token was stolen. Generating a new token with every request helps in catching that. It's described well in this article [http://jaspan.com/improved_persistent_login_cookie_best_practice] – Dhiraj Nov 29 '12 at 18:51
  • It's about never ending battle :) security vs. usability. Sometimes security wins sometimes it don't. Here I think the winning is not worth the price. Issuing new sequencer on every request, might be overkill specially if you have some heavy background actions. And good application design should requre a reauthentication before any security critical changes, thus limiting the damage person can do after taking over remeber me cookie. Of course security critical app would requre what you have presented :) no doubt about it. :) – damiankolasa Nov 29 '12 at 21:41
0

I've been reading a bit about this since I have the same issue.

Barry Jaspan and Charles Miller's technique seems to be unusable (especially in AJAX setups) due to the fact that between generating a new token on the server and applying that in a cookie, as you point out, a lot can happen.

In our case it is the asynchronous nature, but there might be other cases where the value does just not end up in the cookie as it is stored on the server (e.g. navigating away from the page before it loaded).

Barry seems to acknowledge this.

Secondly, invalidating tokens (e.g. on password change) makes you end up with a lot of "ghost" cookies. Each access with one of them invalidates all other sessions (which are at that point likely to have valid ones among them).

Because of these limitations, I think the best solution is a combination of:

  • HTTPS (SSL) use
  • this technique, but without re-generation on every request
  • tracking invalidation by user (to handle second remark above)
  • HTTP-only cookies (to avoid script access to them)

I have sent a message to Barry to consider a notice about this on his page.

smhg
  • 2,159
  • 19
  • 26