Don Smythe
Don Smythe

Reputation: 9804

Flask.session persisting after close browser

I want to be able to detect if a user has closed a browser since last logging into a Flask site. I have read that Flask sessions are supposed to expire on closing the browser, but the session data is stored on the server as far as I can tell and is persisting across browser sessions. How can I clear all session data when the user closes the browser?

mainapp.py:

@mainapp.route('/')
def home():
    if 'user_name' in session:
        logger.debug( 'Logged in as {0}'.format(escape(session['user_name'])))
    return render_template('home.html')

userviews.py:

@userviews.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm(request.form)
    if form.validate_on_submit():
        #get user from db
        session['user_name'] = user.user_name

setup.py:

app.secret_key = 'somethingreallysecret'

Upvotes: 9

Views: 24648

Answers (5)

radko.stulrajter
radko.stulrajter

Reputation: 1

As answered by Amin you can use Flask-SocketIO but as you mentioned the performance will suffer.

You say "session data is stored on the server as far as I can tell" but from that sentence it is not clear whether you use server-side session extension for Flask (e.g. Flask-Session) or you just assume the session data is stored on the server but, in fact, you use Flask built-in session class which is client-side.

If you use client-side sessions then the session info is stored in cookies in the web browser. If session.permanent = False (which is the default) then the session will be deleted when the user closes the browser (as shared by Dan). However, if the browser startup setting is "Open previous windows and tabs" (in Firefox) / "Open tabs from the previous session" (in MS Edge), etc. then the session cookies in the web browser are not deleted but are kept (so when you open the browser again the session still exists).

The potential alternative solution (by Jordan Bonser on https://www.bonser.dev/flask-session-timeout.html) to Flask-SocketIO might be to use before_request function with permanent_session_lifetime set to some reasonable value and session.modified = True so the session lifetime timer is reset every time there is a user interaction. The session data is cleared after defined time of user inactivity.

@app.before_request
def before_request():
    flask.session.permanent = True
    app.permanent_session_lifetime = datetime.timedelta(minutes=20)
    flask.session.modified = True

Upvotes: 0

qff
qff

Reputation: 5892

Unless you're explicitly setting session.permanent = True the session cookie should expire when the browser closes.

Reference: Flask documentation on session.permanent

Upvotes: 2

Dan King
Dan King

Reputation: 584

Per the docs (https://flask.palletsprojects.com/en/1.1.x/api/#flask.session.permanent):

permanent:

"If set to True the session lives for permanent_session_lifetime seconds. The default is 31 days. If set to False (which is the default) the session will be deleted when the user closes the browser."

In the block of code where you set your session variables include this line:

session.permanent = False

E.g.

@app.route("/login", methods=["GET", "POST"])
def login() -> "html":
    if request.method == "GET":
        return render_template(
            "login.html",
        )
    else:
        # Process login form...

        # ...then set session variable
        session.permanent = False
        session["username"] = "some value"
        return render_template(
            "some_secure_page.html",
        )

Upvotes: 0

user9142797
user9142797

Reputation: 41

It seems that contrary to vanilla Flask, the sessions opened in Flask-session are permanent by default, from the documentation:

By default, all non-null sessions in Flask-Session are permanent.

So maybe try to set SESSION_PERMANENT=False?

Upvotes: 4

Amin Alaee
Amin Alaee

Reputation: 1915

Because the flask session uses cookies, the data is persisted even if the user closes the window. You can track use closing the window with Flask-SocketIO.

If you want to remove a specific key from session:

from flask import session
from flask_socketio import SocketIO, emit
from flask.ext.login import current_user, logout_user

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@socketio.on('disconnect')
def disconnect_user():
    logout_user()
    session.pop('yourkey', None)

Upvotes: 13

Related Questions