diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index 7e28614a..e90e9ddf 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -110,6 +110,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->scalarNode('domain')->defaultNull()->end()
->scalarNode('secure')->defaultTrue()->end()
->scalarNode('httpOnly')->defaultTrue()->end()
+ ->scalarNode('partitioned')->defaultFalse()->end()
->arrayNode('split')
->scalarPrototype()->end()
->end()
diff --git a/DependencyInjection/LexikJWTAuthenticationExtension.php b/DependencyInjection/LexikJWTAuthenticationExtension.php
index 07a4b0d4..a91b5712 100644
--- a/DependencyInjection/LexikJWTAuthenticationExtension.php
+++ b/DependencyInjection/LexikJWTAuthenticationExtension.php
@@ -15,6 +15,7 @@
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\Component\HttpKernel\Kernel;
/**
* This is the class that loads and manages your bundle configuration.
@@ -115,6 +116,10 @@ public function load(array $configs, ContainerBuilder $container): void
$cookieProviders = [];
foreach ($config['set_cookies'] as $name => $attributes) {
+ if ($attributes['partitioned'] && Kernel::VERSION < '6.4') {
+ throw new \LogicException(sprintf('The `partitioned` option for cookies is only available for Symfony 6.4 and above. You are currently on version %s', Kernel::VERSION));
+ }
+
$container
->setDefinition($id = "lexik_jwt_authentication.cookie_provider.$name", new ChildDefinition('lexik_jwt_authentication.cookie_provider'))
->replaceArgument(0, $name)
@@ -124,7 +129,8 @@ public function load(array $configs, ContainerBuilder $container): void
->replaceArgument(4, $attributes['domain'])
->replaceArgument(5, $attributes['secure'])
->replaceArgument(6, $attributes['httpOnly'])
- ->replaceArgument(7, $attributes['split']);
+ ->replaceArgument(7, $attributes['split'])
+ ->replaceArgument(8, $attributes['partitioned']);
$cookieProviders[] = new Reference($id);
}
diff --git a/Resources/config/cookie.xml b/Resources/config/cookie.xml
index e47ea10d..e666c700 100644
--- a/Resources/config/cookie.xml
+++ b/Resources/config/cookie.xml
@@ -14,6 +14,7 @@
null
+ false
diff --git a/Resources/doc/1-configuration-reference.rst b/Resources/doc/1-configuration-reference.rst
index 43bf8a90..1ae2be45 100644
--- a/Resources/doc/1-configuration-reference.rst
+++ b/Resources/doc/1-configuration-reference.rst
@@ -140,6 +140,7 @@ when the cookie token extractor is enabled
# domain: null (null means automatically set by symfony)
# secure: true (default to true)
# httpOnly: true
+ # partitioned: false
Automatically generating split cookies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -170,6 +171,7 @@ Keep in mind, that SameSite attribute is **not supported** in
path: /
domain: null
httpOnly: false
+ partitioned: false # Only for Symfony 6.4 or higher
split:
- header
- payload
@@ -180,6 +182,7 @@ Keep in mind, that SameSite attribute is **not supported** in
path: /
domain: null
httpOnly: true
+ partitioned: false # Only for Symfony 6.4 or higher
split:
- signature
diff --git a/Security/Http/Cookie/JWTCookieProvider.php b/Security/Http/Cookie/JWTCookieProvider.php
index 54dbed6b..460af6e7 100644
--- a/Security/Http/Cookie/JWTCookieProvider.php
+++ b/Security/Http/Cookie/JWTCookieProvider.php
@@ -4,6 +4,7 @@
use Lexik\Bundle\JWTAuthenticationBundle\Helper\JWTSplitter;
use Symfony\Component\HttpFoundation\Cookie;
+use Symfony\Component\HttpKernel\Kernel;
/**
* Creates secure JWT cookies.
@@ -18,8 +19,9 @@ final class JWTCookieProvider
private $defaultSecure;
private $defaultHttpOnly;
private $defaultSplit;
+ private $defaultPartitioned;
- public function __construct(?string $defaultName = null, ?int $defaultLifetime = 0, ?string $defaultSameSite = Cookie::SAMESITE_LAX, ?string $defaultPath = '/', ?string $defaultDomain = null, bool $defaultSecure = true, bool $defaultHttpOnly = true, array $defaultSplit = [])
+ public function __construct(?string $defaultName = null, ?int $defaultLifetime = 0, ?string $defaultSameSite = Cookie::SAMESITE_LAX, ?string $defaultPath = '/', ?string $defaultDomain = null, bool $defaultSecure = true, bool $defaultHttpOnly = true, array $defaultSplit = [], bool $defaultPartitioned = false)
{
$this->defaultName = $defaultName;
$this->defaultLifetime = $defaultLifetime;
@@ -29,6 +31,11 @@ public function __construct(?string $defaultName = null, ?int $defaultLifetime =
$this->defaultSecure = $defaultSecure;
$this->defaultHttpOnly = $defaultHttpOnly;
$this->defaultSplit = $defaultSplit;
+ $this->defaultPartitioned = $defaultPartitioned;
+
+ if ($defaultPartitioned && Kernel::VERSION < '6.4') {
+ throw new \LogicException(sprintf('The `partitioned` option for cookies is only available for Symfony 6.4 and above. You are currently on version %s', Kernel::VERSION));
+ }
}
/**
@@ -37,7 +44,7 @@ public function __construct(?string $defaultName = null, ?int $defaultLifetime =
* For each argument (all args except $jwt), if omitted or set to null then the
* default value defined via the constructor will be used.
*/
- public function createCookie(string $jwt, ?string $name = null, $expiresAt = null, ?string $sameSite = null, ?string $path = null, ?string $domain = null, ?bool $secure = null, ?bool $httpOnly = null, array $split = []): Cookie
+ public function createCookie(string $jwt, ?string $name = null, $expiresAt = null, ?string $sameSite = null, ?string $path = null, ?string $domain = null, ?bool $secure = null, ?bool $httpOnly = null, array $split = [], ?bool $partitioned = null): Cookie
{
if (!$name && !$this->defaultName) {
throw new \LogicException(sprintf('The cookie name must be provided, either pass it as 2nd argument of %s or set a default name via the constructor.', __METHOD__));
@@ -47,6 +54,10 @@ public function createCookie(string $jwt, ?string $name = null, $expiresAt = nul
throw new \LogicException(sprintf('The cookie expiration time must be provided, either pass it as 3rd argument of %s or set a default lifetime via the constructor.', __METHOD__));
}
+ if ($partitioned && Kernel::VERSION < '6.4') {
+ throw new \LogicException(sprintf('The `partitioned` option for cookies is only available for Symfony 6.4 and above. You are currently on version %s', Kernel::VERSION));
+ }
+
$jwtParts = new JWTSplitter($jwt);
$jwt = $jwtParts->getParts($split ?: $this->defaultSplit);
@@ -63,7 +74,8 @@ public function createCookie(string $jwt, ?string $name = null, $expiresAt = nul
$secure ?: $this->defaultSecure,
$httpOnly ?: $this->defaultHttpOnly,
false,
- $sameSite ?: $this->defaultSameSite
+ $sameSite ?: $this->defaultSameSite,
+ $partitioned ?: $this->defaultPartitioned,
);
}
}