Python session SAMESITE=None not being set
Just to expand on this, using flask application config just as you've mentioned, you can set everything except when setting SESSION_COOKIE_SAMESITE=None
Google Chrome doesn't seem to place the value as "None", which then defaults to "Lax".
How i worked around this problem was to add the cookie back into the response header. First I had to get the cookie value because using request.cookies.get("my_cookie")
doesn't seem to extract the cookie value from the response and always appears as None.
secondly, using the response.set_cookie()
still doesn't set the samesite=None
value. I have no idea why because i'm using the latest version of flask
and Werkzeug
which apparently should fix the problem but it doesn't. After lots of testing, I found out using the response.headers.add()
works to add a Set-Cookie:
header but I needed a way to extract the cookie value to ensure I can get the same session. After looking through flask docs and other online forums. I found out that I can actually call SecureCookieSessionInterface
class and get the signed session from there.
from flask import sessionfrom flask.sessions import SecureCookieSessionInterface# where `app` is your Flask Application name.session_cookie = SecureCookieSessionInterface().get_signing_serializer(app)
Lastly, i had to ensure that the same session is added to the response after the request has been established rather than calling it on every route which doesn't seem feasible within a full fledged application. This is done by using the after_request decorator which runs automatically after a request.
@app.after_requestdef cookies(response): same_cookie = session_cookie.dumps(dict(session)) response.headers.add("Set-Cookie", f"my_cookie={same_cookie}; Secure; HttpOnly; SameSite=None; Path=/;") return response
What I noticed in Chrome is that, it basically sets a duplicate cookie with the same signed value. Since both are identical with one having samesite=None
in the response header and the other blocked by Chrome seems to be ignored. Thus, the session is validated with the flask app and access is allowed.
A mistake easily made (as I did) is to confuse None
with "None"
. Be sure to use the string instead of the python literal like so:
response.set_cookie("key", value, ..., samesite="None")
samesite=None
would indeed be ignored and defaults to "Lax".
From: https://github.com/GoogleChromeLabs/samesite-examples/blob/master/python-flask.md
Assuming you're on the latest version of werkzeug
that includes the fix to this issue, you should be able to useset_cookie()
like this:
from flask import Flask, make_responseapp = Flask(__name__)@app.route('/')def hello_world(): resp = make_response('Hello, World!'); resp.set_cookie('same-site-cookie', 'foo', samesite='Lax'); resp.set_cookie('cross-site-cookie', 'bar', samesite='None', secure=True); return resp
Otherwise, you can stillset the headerexplicitly:
from flask import Flask, make_responseapp = Flask(__name__)@app.route('/')def hello_world(): resp = make_response('Hello, World!'); resp.set_cookie('same-site-cookie', 'foo', samesite='Lax'); # Ensure you use "add" to not overwrite existing cookie headers resp.headers.add('Set-Cookie','cross-site-cookie=bar; SameSite=None; Secure') return resp