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.
Answer from Thomas Orozco on Stack Overflowsecurity - How to properly and securely handle cookies and sessions in Python's Flask? - Stack Overflow
Is the default flask session still not secure?
How to implement Authentication when using Flask as backend and Vue.JS as frontend
There's nothing really wrong with using session cookies with an API. A cookie is just a header, every http client can use them, and they're especially convenient for web apps.
A long lived jwt ( no refresh token ) is also fine if you validate against your database on every request and have a system to blacklist tokens.
The refresh token flow is pretty much designed for high traffic APIs where you can't afford to verify access on every request.
Until you have enough traffic where that becomes a problem, you don't need to worry about it.
Flask-Login vs. Flask-User vs Flask-Security
I think Flask-Security is deprecated right now. I never used Flask-User on a project. Flask-Login was always my choice for handling sessions/users. You can make your own session handler. I recommend using JWT for authentication & authorization.
More on reddit.comThe 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.
I would recommend you go with the Flask KVSession plugin with the simplekv module to persist the session information.
Conceptually, Flask KVSession provides an implementation for Method #1 described above using the Flask session interface. That way you don't have to alter your code to get it running, and you can use the extension methods to do additional things such as session expiration. It also takes care of the session signing, and does some basic checks to prevent tampering. You will still want to do this over HTTPS to absolutely prevent session stealing however.
Simplekv is the actual module that handles the writing and reading to various data storage formats. This can be as simple as a flat file, as fast as Redis, or as persistent as a database (NoSQL or otherwise). The reason this is a separate module is so Flask KVSession can just be a plain adapter to Flask without having to know about the storage mechanism.
You can find code samples at http://flask-kvsession.readthedocs.org/en/latest/. If you need more examples, I can provide one.
Alternatively, if you need a more enterprise and heavyweight server sided implementation for Flask, you can also look at this recipe using Beaker which works as WSGI middleware (meaning other frameworks also use it). http://flask.pocoo.org/snippets/61/. The Beaker API is at http://beaker.readthedocs.org/en/latest/.
One advantage Beaker provides over Flask KVSession is that Beaker will lazy load sessions, so if you don't read the session information, it won't make a connection to the database on every call. However, Beaker depends on SQLAlchemy which is going to be a larger module than simplekv module.
Unless that specific performance case is important, I would still go with Flask KVSession because of its slightly simpler API and smaller code base.