From 7392892bab8897c5bec08dbfd7209d5b38da160d Mon Sep 17 00:00:00 2001 From: Alexander Gutev Date: Wed, 15 Apr 2026 15:24:04 +0200 Subject: [PATCH 1/3] Add JWT_COOKIE_PARTITIONED config option. This controls whether the JWT access and CSRF protect token cookies are marked as partitioned. --- flask_jwt_extended/config.py | 4 ++++ flask_jwt_extended/jwt_manager.py | 1 + flask_jwt_extended/utils.py | 2 ++ 3 files changed, 7 insertions(+) diff --git a/flask_jwt_extended/config.py b/flask_jwt_extended/config.py index 7d25651..d39809f 100644 --- a/flask_jwt_extended/config.py +++ b/flask_jwt_extended/config.py @@ -118,6 +118,10 @@ def cookie_secure(self) -> bool: def cookie_domain(self) -> str: return current_app.config["JWT_COOKIE_DOMAIN"] + @property + def cookie_partitioned(self) -> bool: + return current_app.config["JWT_COOKIE_PARTITIONED"] + @property def session_cookie(self) -> bool: return current_app.config["JWT_SESSION_COOKIE"] diff --git a/flask_jwt_extended/jwt_manager.py b/flask_jwt_extended/jwt_manager.py index 7f0d967..9093a32 100644 --- a/flask_jwt_extended/jwt_manager.py +++ b/flask_jwt_extended/jwt_manager.py @@ -199,6 +199,7 @@ def _set_default_configuration_options(app: Flask) -> None: app.config.setdefault("JWT_COOKIE_DOMAIN", None) app.config.setdefault("JWT_COOKIE_SAMESITE", None) app.config.setdefault("JWT_COOKIE_SECURE", False) + app.config.setdefault("JWT_COOKIE_PARTITIONED", False) app.config.setdefault("JWT_CSRF_CHECK_FORM", False) app.config.setdefault("JWT_CSRF_IN_COOKIES", True) app.config.setdefault("JWT_CSRF_METHODS", ["POST", "PUT", "PATCH", "DELETE"]) diff --git a/flask_jwt_extended/utils.py b/flask_jwt_extended/utils.py index d42f582..8874a90 100644 --- a/flask_jwt_extended/utils.py +++ b/flask_jwt_extended/utils.py @@ -301,6 +301,7 @@ def set_access_cookies( domain=domain or config.cookie_domain, path=config.access_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) if config.cookie_csrf_protect and config.csrf_in_cookies: @@ -313,6 +314,7 @@ def set_access_cookies( domain=domain or config.cookie_domain, path=config.access_csrf_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) From d777502de3215c189080110676cc18058bfa0d9c Mon Sep 17 00:00:00 2001 From: Alexander Gutev Date: Thu, 16 Apr 2026 15:35:45 +0200 Subject: [PATCH 2/3] Add documentation of JWT_COOKIE_PARTITIONED flag. --- docs/options.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/options.rst b/docs/options.rst index fd71e06..7869bcd 100644 --- a/docs/options.rst +++ b/docs/options.rst @@ -44,6 +44,7 @@ Overview: * `JWT_COOKIE_DOMAIN`_ * `JWT_COOKIE_SAMESITE`_ * `JWT_COOKIE_SECURE`_ + * `JWT_COOKIE_PARTITIONED`_ * `JWT_REFRESH_COOKIE_NAME`_ * `JWT_REFRESH_COOKIE_PATH`_ * `JWT_SESSION_COOKIE`_ @@ -358,6 +359,18 @@ These are only applicable if a route is configured to accept JWTs via cookies. Default: ``False`` +.. _JWT_COOKIE_PARTITIONED: +.. py:data:: JWT_COOKIE_PARTITIONED + + Controls if the ``partitioned`` flag should be placed on cookies + created by this extension. + + Cookies Having Independent Partitioned State (CHIPS, also known as + Partitioned cookies) allows developers to opt a cookie into + partitioned storage, with a separate cookie jar per top-level + site. + + Default: ``False`` .. _JWT_REFRESH_COOKIE_NAME: .. py:data:: JWT_REFRESH_COOKIE_NAME From 2581c919547fbaadba84682e873438262f4adee2 Mon Sep 17 00:00:00 2001 From: Alexander Gutev Date: Thu, 16 Apr 2026 15:37:45 +0200 Subject: [PATCH 3/3] Add partitioned flag to all set_cookie calls. --- flask_jwt_extended/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flask_jwt_extended/utils.py b/flask_jwt_extended/utils.py index 8874a90..d8f8ab5 100644 --- a/flask_jwt_extended/utils.py +++ b/flask_jwt_extended/utils.py @@ -356,6 +356,7 @@ def set_refresh_cookies( domain=domain or config.cookie_domain, path=config.refresh_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) if config.cookie_csrf_protect and config.csrf_in_cookies: @@ -368,6 +369,7 @@ def set_refresh_cookies( domain=domain or config.cookie_domain, path=config.refresh_csrf_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) @@ -406,6 +408,7 @@ def unset_access_cookies(response: Response, domain: Optional[str] = None) -> No domain=domain or config.cookie_domain, path=config.access_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) if config.cookie_csrf_protect and config.csrf_in_cookies: @@ -418,6 +421,7 @@ def unset_access_cookies(response: Response, domain: Optional[str] = None) -> No domain=domain or config.cookie_domain, path=config.access_csrf_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) @@ -444,6 +448,7 @@ def unset_refresh_cookies(response: Response, domain: Optional[str] = None) -> N domain=domain or config.cookie_domain, path=config.refresh_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned ) if config.cookie_csrf_protect and config.csrf_in_cookies: @@ -456,6 +461,7 @@ def unset_refresh_cookies(response: Response, domain: Optional[str] = None) -> N domain=domain or config.cookie_domain, path=config.refresh_csrf_cookie_path, samesite=config.cookie_samesite, + partitioned=config.cookie_partitioned )