Answer: Impact of the default SameSite=Lax
With Flask 3.x the default value of SESSION_COOKIE_SAMESITE changed from unset/None to the string 'Lax'. For a client‑side (signed) session this means:
- The cookie is sent on top‑level cross‑site GET navigations (e.g., clicking a link that leads to another site).
- The cookie is withheld on:
- cross‑site POST requests
- cross‑site sub‑resource requests (images, scripts, iframes)
- cross‑site AJAX/fetch calls
- Therefore any legacy cross‑site authentication flow that relies on a POST, an iframe‑based login, or an AJAX call to obtain or refresh the session will no longer receive the session cookie and will appear to lose the session.
Likely explanation vs. confirmed facts
Likely explanation (based on the version change): The framework tightened CSRF protection by defaulting to Lax, which blocks the cookie on the request types most commonly used for state‑changing cross‑site interactions.
Confirmed facts (from Flask’s configuration model):
- The cookie attribute is controlled solely by
SESSION_COOKIE_SAMESITE; there is no separate SAME_SITE key.
- Whether you use Flask’s built‑in client‑side sessions or Flask‑Session (server‑side storage) does not change how the SameSite attribute is applied – the setting governs the identifier cookie in both cases.
- Setting
SESSION_COOKIE_SAMESITE='None' restores transmission on all cross‑site requests, but it must be paired with SESSION_COOKIE_SECURE=True (and usually SESSION_COOKIE_HTTPONLY=True) because modern browsers reject SameSite=None without the Secure flag.
Steps to restore SameSite=None while keeping secure handling
- Ensure the application is served over HTTPS (or behind a trusted proxy that sets
X-Forwarded-Proto: https).
- In your Flask config, set:
app.config.update(
SESSION_COOKIE_SAMESITE='None',
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True
)
- Because
SameSite=None removes the SameSite‑based CSRF mitigation, add CSRF tokens (e.g., Flask‑WTF or a custom double‑submit cookie) to all state‑changing endpoints.
- Test: open DevTools → Application → Cookies, verify the
Set-Cookie header includes SameSite=None; Secure; HttpOnly. Then make a cross‑site POST or AJAX request and confirm the cookie is sent back.
Effect of enabling Flask‑Session
Enabling Flask‑Session (SESSION_TYPE='filesystem', 'redis', etc.) stores the session payload server‑side and the cookie holds only a random session identifier. The SameSite behavior is unchanged: the identifier cookie still obeys SESSION_COOKIE_SAMESITE. Therefore the same configuration (None+Secure+HttpOnly) restores legacy cross‑site flows when using Flask‑Session.
Missing diagnostic detail
If you are not serving over HTTPS (or cannot guarantee the Secure flag will be set by a proxy), setting SESSION_COOKIE_SECURE=True will cause the cookie to be omitted entirely. Please confirm whether your deployment terminates HTTPS at the application level or at a trusted front‑end proxy.