27

How do I create a new clean session and invalidate the current one in Flask?

Do I use make_null_session() or open_session()?

ʇsәɹoɈ
  • 22,757
  • 7
  • 55
  • 61
Tyilo
  • 28,998
  • 40
  • 113
  • 198

4 Answers4

31

I do this by calling session.clear().

EDIT:

After reading your comment in another answer, I see that you're trying to prevent a replay attack that might be made using a cookie that was issued in the past. I solved that problem as much as possible* with this approach:

  • Override SecureCookieSessionInterface.save_session(), copying the code from the overridden version rather than calling it.
  • When the overridden version of save_session() calls save_cookie(), make it pass a session_expires argument 30 minutes in the future. This causes cookies more than 30 minutes old to be considered invalid.
  • Make the overridden version of save_session() update a session variable every so often, to make sure the cookie and its session_expires time get rewritten regularly. (I name this session variable '_refresh' and store the current time in it, then rewrite it only if more than a few seconds have passed since the last-stored time. This optimization avoids rewriting the cookie on every HTTP request.)

Duplicating Flask code in the custom save_session() makes this approach a bit ugly and brittle, but it is necessary in order to change the arguments passed to save_cookie(). It would be nice if Flask made this easier, or at least implemented its own safeguard against replay attacks.

*WARNING: This approach by itself will not stop replay attacks that might happen during a session cookie's valid lifetime. This fundamental problem with cookie-based sessions is discussed in RFC 6896 and A Secure Cookie Protocol by Liu, Kovacs, Huang, Gouda.

Community
  • 1
  • 1
ʇsәɹoɈ
  • 22,757
  • 7
  • 55
  • 61
  • 1
    This doesn't seem to invalidate the current session. Do you know if that is possible to do? – Tyilo Dec 06 '12 at 01:24
  • 2
    Flask's built-in sessions are cookie-based with hashes and timestamps for validation, so there's no such thing as invalidating them in the way that you would with a key-based database-storage-backed session. You could override `SecureCookieSessionInterface.save_session()` to call `save_cookie()` with a `session_expires` argument in the past, but why bother? Calling `session.clear()` removes all data from the session, leaving it empty. Isn't that good enough? – ʇsәɹoɈ Dec 06 '12 at 07:35
  • Oh, I see what you're after. I just edited my answer with an approach that should help you. – ʇsәɹoɈ Dec 06 '12 at 07:47
  • 1
    If `session_expires` set to 30 minutes, users will be logged out from their sessions after 30 minutes of inactivity. – Taha Jahangir Mar 28 '17 at 03:24
12

If you have security concerns (and everyone should have) There is the answer:

This is not REALLY possible

Flask uses cookie-based sessions. When you edit or delete session, you send a REQUEST to CLIENT to remove the cookie, normal clients (browsers) will do. But if session hijacked by an attacker, the attacker's session remains valid.

Taha Jahangir
  • 4,774
  • 2
  • 42
  • 49
  • I am not certain what you mean by saying that normal clients (browsers) would remove the cookie on logout. I don't see that happening in Chrome or FF. Now when I say logout, I would expect the framework, Flask in our case, to invalidate the session in the backend, irrespective of what the client prefers to do with the cookie. I would agree that Flask-Login is apparently handling sessions with cookies or more precisely, the logout_user() from Flask-Login is may be not doing what it sounds to be doing. – qre0ct Oct 27 '16 at 10:32
11

You can add an after_request callback to remove the session cookie if a particular flag is set:

@app.after_request
def remove_if_invalid(response):
    if "__invalidate__" in session:
        response.delete_cookie(app.session_cookie_name)
    return response

Then you simply set that session key whenever you want to invalidate the session:

@app.route("/logout")
def logout():
    session["__invalidate__"] = True
    return redirect(url_for("index"))

See also: http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.BaseResponse.delete_cookie

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • 1
    But will this invalidate the current session? I want to make it so that the user tries to use the old session cookie, it will not work. Is this possible? – Tyilo Dec 06 '12 at 06:48
  • @Tyilo - Are you worried about replay attacks? – Sean Vieira Dec 06 '12 at 07:28
  • @Tyilo - You'll want to take a look at http://stackoverflow.com/a/12472337/135978 for a good starting point there. – Sean Vieira Dec 06 '12 at 17:44
2

If you use default flask sessions and set the app.permanent_session_lifetime, then the session will not work if a user tries to replay the same session as long as the session has expired.If you look at the source code for open_session, there is line:

max_age = total_seconds(app.permanent_session_lifetime)
try:            
    data = s.loads(val, max_age=max_age)
    return self.session_class(data)
    except BadSignature:
        return self.session_class()
codegeek
  • 32,236
  • 12
  • 63
  • 63