mbr / flask-kvsession

A drop-in replacement for Flask's session handling using server-side sessions.
http://pythonhosted.org/Flask-KVSession/
MIT License
168 stars 53 forks source link

session.regenerate() Force User To Sign Out #33

Closed saeid-p closed 9 years ago

saeid-p commented 9 years ago

I implemented a logic to refresh user last access to the system and stop user from being signed out after session expires. My session expires after 10 minutes. I implemented this logic this way:

@vapor_app.before_request
def before_request():
    g.user = current_user
    session.permanent = True
    session.regenerate()

This logic works just fine when I use the system. But as soon as I refresh the page once (With F5), it logs me out of the system. How should I refresh last access date and avoid this error.

mbr commented 9 years ago

Sorry it took me so long to get to this.

I implemented a logic to refresh user last access to the system and stop user from being signed out after session expires. My session expires after 10 minutes. I implemented this logic this way:

That pattern is not well supported, "by design", to minimize backend writes. The only way to keep a user logged in constantly is by somehow updating the session on the backend, which takes a write in addition to the read each time a request is made.

This logic works just fine when I use the system. But as soon as I refresh the page once (With F5), it logs me out of the system. How should I refresh last access date and avoid this error.

The regenerate() call will actually replace the session with a new one, including a fresh id. Doing it in a before_requet hook might interfere with the actual session loading. I will have to double check that one.

There may be a way to have the "expires-after-activity"-session behavior by generating session specific keys and signing cookies, but I will have to look into that one (and it will be an addition to Flask-KVSession).

mbr commented 9 years ago

Actually, regenerate() will destroy the sesssion on the server side, but will leave any session data that is currently loaded intact and mark it as modified. As soon as you send a reply, a new session will be recreated.

This will, however, not work if the session has not been loaded yet. So a solution for your case is probably calling regenerate() slightly later.

saeid-p commented 9 years ago

Thanks for the reply. I implemented a custom logic for our scenario and fixed the issue. I'll try to make it more generic and suggest it as a pull request soon.

mbr commented 9 years ago

I should note that this has initially been a feature, not a bug: If a session gets stolen by an attacker and does not have a fixed expiration date, it never expires (because he can prolong it indefinitely). With a fixed expiration, users will have to re-login occasionally, but there won't be any eternal sessions.

On the other hand, this can be worked around by regenerating the session occasionally. It may even be prudent to have two timeouts, one short "keepalive" variant and a longer definite session timeout.