Skip to content

Commit ce08bc7

Browse files
authored
add SESSION_COOKIE_PARTITIONED config (#5499)
2 parents 6f2014d + 9efc1eb commit ce08bc7

File tree

5 files changed

+34
-0
lines changed

5 files changed

+34
-0
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Unreleased
1515
through the ``MAX_CONTENT_LENGTH`` config. Added
1616
``MAX_FORM_MEMORY_SIZE`` and ``MAX_FORM_PARTS`` config. Added documentation
1717
about resource limits to the security page. :issue:`5625`
18+
- Add support for the ``Partitioned`` cookie attribute (CHIPS), with the
19+
``SESSION_COOKIE_PARTITIONED`` config. :issue`5472`
1820

1921

2022
Version 3.0.3

docs/config.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,23 @@ The following configuration values are used internally by Flask:
173173

174174
Default: ``False``
175175

176+
.. py:data:: SESSION_COOKIE_PARTITIONED
177+
178+
Browsers will send cookies based on the top-level document's domain, rather
179+
than only the domain of the document setting the cookie. This prevents third
180+
party cookies set in iframes from "leaking" between separate sites.
181+
182+
Browsers are beginning to disallow non-partitioned third party cookies, so
183+
you need to mark your cookies partitioned if you expect them to work in such
184+
embedded situations.
185+
186+
Enabling this implicitly enables :data:`SESSION_COOKIE_SECURE` as well, as
187+
it is only valid when served over HTTPS.
188+
189+
Default: ``False``
190+
191+
.. versionadded:: 3.1
192+
176193
.. py:data:: SESSION_COOKIE_SAMESITE
177194
178195
Restrict how cookies are sent with requests from external sites. Can

src/flask/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class Flask(App):
189189
"SESSION_COOKIE_PATH": None,
190190
"SESSION_COOKIE_HTTPONLY": True,
191191
"SESSION_COOKIE_SECURE": False,
192+
"SESSION_COOKIE_PARTITIONED": False,
192193
"SESSION_COOKIE_SAMESITE": None,
193194
"SESSION_REFRESH_EACH_REQUEST": True,
194195
"MAX_CONTENT_LENGTH": None,

src/flask/sessions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ def get_cookie_samesite(self, app: Flask) -> str | None:
224224
"""
225225
return app.config["SESSION_COOKIE_SAMESITE"] # type: ignore[no-any-return]
226226

227+
def get_cookie_partitioned(self, app: Flask) -> bool:
228+
"""Returns True if the cookie should be partitioned. By default, uses
229+
the value of :data:`SESSION_COOKIE_PARTITIONED`.
230+
231+
.. versionadded:: 3.1
232+
"""
233+
return app.config["SESSION_COOKIE_PARTITIONED"] # type: ignore[no-any-return]
234+
227235
def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None:
228236
"""A helper method that returns an expiration date for the session
229237
or ``None`` if the session is linked to the browser session. The
@@ -338,6 +346,7 @@ def save_session(
338346
domain = self.get_cookie_domain(app)
339347
path = self.get_cookie_path(app)
340348
secure = self.get_cookie_secure(app)
349+
partitioned = self.get_cookie_partitioned(app)
341350
samesite = self.get_cookie_samesite(app)
342351
httponly = self.get_cookie_httponly(app)
343352

@@ -354,6 +363,7 @@ def save_session(
354363
domain=domain,
355364
path=path,
356365
secure=secure,
366+
partitioned=partitioned,
357367
samesite=samesite,
358368
httponly=httponly,
359369
)
@@ -374,6 +384,7 @@ def save_session(
374384
domain=domain,
375385
path=path,
376386
secure=secure,
387+
partitioned=partitioned,
377388
samesite=samesite,
378389
)
379390
response.vary.add("Cookie")

tests/test_basic.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ def test_session_using_session_settings(app, client):
293293
SESSION_COOKIE_DOMAIN=".example.com",
294294
SESSION_COOKIE_HTTPONLY=False,
295295
SESSION_COOKIE_SECURE=True,
296+
SESSION_COOKIE_PARTITIONED=True,
296297
SESSION_COOKIE_SAMESITE="Lax",
297298
SESSION_COOKIE_PATH="/",
298299
)
@@ -315,6 +316,7 @@ def clear():
315316
assert "secure" in cookie
316317
assert "httponly" not in cookie
317318
assert "samesite" in cookie
319+
assert "partitioned" in cookie
318320

319321
rv = client.get("/clear", "http://www.example.com:8080/test/")
320322
cookie = rv.headers["set-cookie"].lower()
@@ -324,6 +326,7 @@ def clear():
324326
assert "path=/" in cookie
325327
assert "secure" in cookie
326328
assert "samesite" in cookie
329+
assert "partitioned" in cookie
327330

328331

329332
def test_session_using_samesite_attribute(app, client):

0 commit comments

Comments
 (0)