Flask - Cookie and Token Sessions Simultaneously
Dealing with sessions in Flask applications is rather simple! There is plenty of choice in pre-rolled implementations that is more or less plug-and-play.
However, sometimes you may want (or need) to colour outside the lines, where a cookie-cutter implentation either doesn’t work, or gets in the way.
One such scenario is if you have an application which needs to act both as a web front-end, with your typical cookie-based sessions, as well as an API endpoint. Requiring cookies when you’re acting as an API endpoint isn’t particularly nice, tokens in the request header is the way to go! So how can you get Flask sessions to work with both these methods of identification?
Perhaps at this point, I should add that you might be best served by reconsidering your strategy here, and make the API endpoint a distinct application from the one driving your UI. You can still share all your code for your models and logic and can even make use of a layer 7 load balancer to deal with the separation for you. But be it due to retrofitting, time constraint, legacy or otherwise imposed design.. here goes;
Since Flask is a pretty lightweight framework, it’s easily extended or wrestled into submission. Luckily for us, it offers a pluggable way to write your own session handling!
I’ve put a small example application with a custom session interface on
GitHub, which
allows what we’ve previously discussed. You can either distinguish sessions by
a cookie, if present, or a header of your chosing (cookie trumps header, if
both are present). This header defaults to the
de-facto standard X-Auth-Header
in the example, but you can configure this
easily.
For ease of use, the datastore used to store the sessions is memcached. But
it’s very easily replaced by any other datastore.
The example is as small and compact as possible while remaining runnable. There are no “bells and whistles” such as actual authentication, that’s for you to handle outside of the session handler. You will also most likely want to extend the error checking and handling.
Do note - there’s a docker-compose file
included in the repository, which will enable you to quickly get up and
running.
Alternatively you can simply run pip install -r requirements.txt && ./runserver.py
from
within the app/
directory, provided that you have the required system
dependencies.
Here’s an example of using this session handler with cookies:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Since we don’t send a JSON body containing the key token
, or set the
X-Auth-Token
header, the session handler determines the application should send a cookie.
The example has a session timeout of a mighty 30 seconds (configurable, obviously).
Now, if we were to behave like an API, on the other hand:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
As you can see, we don’t get a cookie sent back, because we behaved like an API client. We can also see that we get a brand new session after the 30 seconds has elapsed.
The example also comes with a test suite for verification. You can execute this
by simply running make tests
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
The tests all run in a docker container, so the first time you run it, you’ll most likely see an image being built, and a memcached image being pulled.
Hope this helps someone!