How to properly and securely handle cookies and sessions in Python's Flask?

cookies, flask, python, security, session

Solution

The background

Method #1

An easy and safe way to handle sessions is to do the following:

- Use a session cookie that contains a session ID (a random number).

- Sign that session cookie using a secret key (to prevent tempering — this is what itsdangerous does).

- Store actual session data in a database on the server side (index by ID, or use a NoSQL key / value store).

- When a user accesses your page, you read the data from the database.

- When a user logs out, you delete the data from the database.

Note that there are a few drawbacks.

- You need to maintain that database backend (more maintenance)

- You need to hit the database for every request (less performance)

Method #2

Another option is to store all the data in the cookie, and sign (and optionally encrypt) said cookie. This method, however, has numerous shortcomings too:

- This is easier on the backend (less maintenance, better performance).

- You need to be careful to not include data your users should not see in sessions (unless you're encrypting).

- The volume of data you can save in a cookie is limited.

- You can't invalidate an individual session (!).

The code

Flask actually implements signed session cookies already, so it implements method #2.

To get from #2 to #1, all you have to do is:

- Generate random Session IDs (you could use `os.urandom` + `base64`).

- Save session data in a database backend, indexed by Session ID (serialize it using e.g. JSON, Picke if you need Python objects, but avoid if you can).

- Delete sessions from your database backend when a user logs out.

Make sure you're protected against session fixation attacks. To do so, make sure you generate a new session ID when a user logs in, and do not reuse their existing session ID.

Also, make sure you implement expiration on your sessions (just a matter of adding a "last-seen" timestamp).

You could most likely get some inspiration from Django's implementation.

Problem

In application I am writing at the moment I've been saving in users browser a cookie that had session ID stored inside, and that ID was used as a reference to a session stored in the database containing user's information including the fact if the user is logged in properly. I wanted to review the security of my solution and I stared to look into how I should be setting up cookies upon login, what to store in server side stored session and how to destroy that information on logout since as of now my users were staying logged in for ages, which was not my intention. The problem I have is no definite answer on how to handle the whole user login/session/logout issue properly in Flask - some people are talking about using Flask's Response.delete_cookie() function, others to expire it using .set_cookie() with zero expiration time, others are mentioning Flask's session module, other itsdangerous module... What is the most secure, right and proper way of handling that in terms of modules that should be used with Flask, code examples and so on?

Original source