Clodoaldo Neto Clodoaldo Neto - 28 days ago 14
Python Question

Flask session does not JSON serialize cookie

I'm using Flask's session which sets a signed cookie header in the response.

from flask import session


This sets a cookie named session with
a = 1
.

a = session.get('a', None)
session['a'] = 1
return jsonify(a = a)


The
jsonify
in the code is just to show that the cookie is being read at the next request, and it is. This is the response to the second request

{
"a": 1
}


I need to read the cookie at the client. So I want it to be JSON encoded. This is the Set-Cookie header in the response

Set-Cookie: session=eyJhIjoxfQ.BeUPPQ.Al5bwLzcAsN2f15mdREzhGWP1uc; HttpOnly; Path=/


It is not JSON serialized.

Flask version is 0.10.1. Since version 0.10 it uses session from
itsdangerous
which main advantage is to JSON serialize the cookies in instead of the Pickle serialization used before.

What am I missing? Flask version is 0.10.1

Answer

You've misunderstood the format of the default Flask session implementation. The session object produces cryptographically signed JSON that is then compressed and base64-encoded to store session values making sure that a client cannot tamper with the values stored in it.

This is change from the previous format using pickle to limit the damage an attacker can do if the server-side secret was compromised (see a blog post of mine why pickle can be dangerous).

In other words, all Flask did is swap out the serializer, from pickle to an extended tagged JSON format, but the pre-existing cryptographic signature and compression has been left in place.

As such that format is not really suitable for decoding again on the client side (you'd have to decode the base64 and decompress the data, split out the signature, and you may have to interpret the extra type tagging). You could switch the session implementations for that but that is very much not recommended.

If you want to share data with the client-side, you could just embed data into page in a <script> block with var session_data = {{data|tojson|safe}};, or set a separate cookie with the data.