patb
patb

Reputation: 1816

Flask permanent session: where to define them?

By default, Flask uses volatile sessions, which means the session cookie is set to expire when browser closes. In order to use permanent sessions, which will use a cookie with a defined expiration date, one should set session.permanent = True, as is mentioned in this question., and the expiration date will be set based on config['PERMANENT_SESSION_LIFETIME'].

I am surprised that session lifetime is defined in config file, yet it is not possible to request the use of permanent sessions through configuration, such as a config['USE_PERMANENT_SESSION'] = True. But so be it.

My question is: if you do want permanent sessions, what is the best place to define them ? Is it in an @app.before_request function as proposed in mentioned question ? But that would mean setting it over again at each request ? It seems that once set, session.permanent remains true till end of session.

Permanent sessions are generally used after sign-in, so maybe the best place to request them is while processing login_user() ? So is the best policy to use volatile session cookies for all anonymous pages, and switch to permanent sessions by doing a session.permanent = True at sign-in ?

And one might want to set a different lifetime depending on whether it is the ordinary session cookie, or the remember_me cookie. What would be the best way to achieve this ?

Upvotes: 42

Views: 36310

Answers (4)

L.Lauenburg
L.Lauenburg

Reputation: 472

As @Hooloovoo13 indicated in his comment to Mikey's reply (with a dead link), you could use the Flask-Session extension to get full control over your Flask sessions. It lets you configure the session-specific parameters when setting up the application:

from flask import Flask
from flask_session import Session


app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
Session(app) 

Although the code above is actually pointless since the Flask-Session extension default value for SESSION_PERMANENT is True:

SESSION_PERMANENT | Whether use permanent session or not, default to be True only since the default value

Upvotes: 0

Kaiwen Sun
Kaiwen Sun

Reputation: 199

Should you use PERMANENT_SESSION_LIFETIME and session.permanent?

What you actually want to do is probably expiring users' sign-in status. However, this configuration expires the session object/cookie which contains the users' sign-in status as well as (potentially) some other data that you stored in session.

Do you need to set session.permanent?

According to Flask's doc:

Flask’s default cookie implementation validates that the cryptographic signature is not older than this value.

session.permanent is an add-on of PERMANENT_SESSION_LIFETIME. Sometimes it is okay if you do not set session.permanent to True.

If you do not set session.permanent, the session cookie's lifetime will not be affected by PERMANENT_SESSION_LIFETIME. But Flask will look at PERMANENT_SESSION_LIFETIME and a timestamp in the session cookie, to see if the session cookie is still valid. If the timestamp is too older than specified by PERMANENT_SESSION_LIFETIME, it will be ignored. But the cookie still exists.

This is how Flask ignores session cookie:

def open_session(self, app, request):
    s = self.get_signing_serializer(app)
    if s is None:
        return None
    val = request.cookies.get(app.session_cookie_name)
    if not val:
        return self.session_class()
    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()

If you set session.permanent=True, the validation will still be done. And what's more, the session cookie will expire and be deleted from the browser after PERMANENT_SESSION_LIFETIME.

This is how PERMANENT_SESSION_LIFETIME control the expiration of the cookie:

def get_expiration_time(self, app, session):
    if session.permanent:
        return datetime.utcnow() + app.permanent_session_lifetime


def save_session(self, app, session, response):
    ...
    expires = self.get_expiration_time(app, session)
    val = self.get_signing_serializer(app).dumps(dict(session))
    response.set_cookie(
        app.session_cookie_name,
        val,
        expires=expires,
        httponly=httponly,
        domain=domain,
        path=path,
        secure=secure,
        samesite=samesite
    )

Do you need to set session.permanent for every request?

session.permanent by default is actually session['_permanent']. Its value will stay in session. But if you are going to assign it only when users sign in, keep alert by checking how users can by-pass the sign-in route to sign in. For example, by signing up.

Upvotes: 11

tinyhare
tinyhare

Reputation: 2401

I choose what you said "login_user()"

@asset.route('/login', methods=['GET', 'POST'])
def login():
    #After Verify the validity of username and password
    session.permanent = True

if it set at app.before_request, This will lead to set them too may times.

Upvotes: 6

mikey8989
mikey8989

Reputation: 504

I'm surprised no on has answered this question. It seems like there should be some type of config variable SESSION_PERMANENT = True. But unfortunately there isn't. As you mentioned this is the best way to do it.

@app.before_request
def make_session_permanent():
    session.permanent = True

Upvotes: 37

Related Questions