19

I'm using the the Python web framework Flask. I use sessions in my app. For my app called main, I've got the setting main.permanent_session_lifetime = timedelta(days=5), so that a user will remain logged in for 5 days after logging in. But even an active user will be logged out after 5 days. I would like the expiration time to reset each time they visit the site, so you get logged out only after 5 days of inactivity. Most sites work this way. How do I do that with Flask?

Paco
  • 4,520
  • 3
  • 29
  • 53
J-bob
  • 8,380
  • 11
  • 52
  • 85
  • 1
    Flask tries to give you the tools to write something like this yourself. How you define "activity" is website dependent. Is "activity" visiting the site, or something like purchasing a product? As you can see, there couldn't be an option such as "inactivity", you would have to implement it yourself. – Mark Hildreth Nov 04 '13 at 15:41
  • For my case, activity just means visiting the site. If they visit any page on the site before the cookie expires, I would like the expiration to be reset to 5 days from that time. – J-bob Nov 04 '13 at 19:04
  • Look at this answer [https://stackoverflow.com/a/49891626](https://stackoverflow.com/a/49891626) It works for me. – Vlad Feb 11 '20 at 12:59

3 Answers3

26

You can renew the session to the client at each request using a @before_request handler.

Try the following:

@app.before_request
def func():
  session.modified = True
Paolo Casciello
  • 7,982
  • 1
  • 43
  • 42
  • Works beautifully. I've actually wanted the `@app.before_request` feature for other reasons previously, so this is great to know about. – J-bob Nov 06 '13 at 17:09
  • This doesn't work while using server side sessions (flask-kvsession). Any ideas how to fix it? – zengr Jan 04 '14 at 21:59
  • 2
    @zengr this is a problem of flask-kvsession as it says to be "a drop-in replacement for Flask‘s signed cookie-based session management". It doesn't do its work completely. Post a bug report. One workaround may be to call the `.regenerate()` method. – Paolo Casciello Jan 06 '14 at 10:13
  • Yeah, I dumped flask-kvsession and implemented this instead: http://flask.pocoo.org/snippets/75/ – zengr Jan 06 '14 at 19:33
5

Should be enough with:

from datetime import timedelta

# User will be logout after this time of inactivity
PERMANENT_SESSION_LIFETIME = timedelta(minutes=30)
SESSION_REFRESH_EACH_REQUEST = True

https://flask.palletsprojects.com/en/1.1.x/config/

GBrian
  • 1,031
  • 11
  • 28
  • No need to set 'SESSION_REFRESH_EACH_REQUEST ' as True because its by default set as True. – PanDe Oct 18 '21 at 03:08
0
  1. Get cookie token from request
    auth_token = request.cookies.get('jwt')
  1. Set token back in response cookie with max_age. As a result, max_age moves forward with each request activity. If there is no activity from the user side then cookie will expire on time.

     response.set_cookie(key="jwt",
                        value=auth_token,
                        max_age=IN_SECONDS,
                        httponly=True,
                        samesite="Strict",
                        )
    

I did it for myself as follows:

I already had a token_rquired_decorator on each API call. So I placed my logic there in the make_response function.

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):

        # some_code here 
        _response, status_code = f(*args, **kwargs)
        return make_response(_response, auth_token, status_code)

    return decorated

In make_response function. I am setting a cookie again that will eventually move my cookie expiry time forward with each request considering as activity.

 def make_response(_response: Dict[str, Any], auth_token: str, status_code: int):
    response = Response(
        json.dumps(_response).encode('utf-8'),
        status=status_code,
        mimetype="application/json"
    )
    response.set_cookie(key="jwt",
                        value=auth_token,
                        max_age=Config.COOKIE_MAX_AGE,
                        httponly=True,
                        samesite="Strict",
                        )
    return response

I hope it will help the community. Don't forget to appreciate it. thanks

Umar Hayat
  • 4,300
  • 1
  • 12
  • 27