From aad9d4824d8d7160d672b6be3e13e11bd53e0d11 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Jun 2025 16:08:14 +0200 Subject: [PATCH 1/8] Allow Symfony ^8.0 --- composer.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 0aaff1e3..9d662f7e 100644 --- a/composer.json +++ b/composer.json @@ -20,20 +20,20 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3", - "symfony/password-hasher": "^6.4|^7.0" + "symfony/password-hasher": "^6.4|^7.0|^8.0" }, "require-dev": { "psr/container": "^1.1|^2.0", "psr/cache": "^1.0|^2.0|^3.0", - "symfony/cache": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/ldap": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/validator": "^6.4|^7.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/ldap": "^6.4|^7.0|^8.0", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4.3|^7.0.3|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", "psr/log": "^1|^2|^3" }, "conflict": { From 156cb0ff029b08e15b34dacce15d91e1118d0839 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Jun 2025 17:50:55 +0200 Subject: [PATCH 2/8] Bump Symfony 8 to PHP >= 8.4 --- composer.json | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 9d662f7e..2cb894cf 100644 --- a/composer.json +++ b/composer.json @@ -16,33 +16,25 @@ } ], "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3", - "symfony/password-hasher": "^6.4|^7.0|^8.0" + "symfony/password-hasher": "^7.4|^8.0", + "symfony/service-contracts": "^2.5|^3" }, "require-dev": { "psr/container": "^1.1|^2.0", "psr/cache": "^1.0|^2.0|^3.0", - "symfony/cache": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", - "symfony/event-dispatcher": "^6.4|^7.0|^8.0", - "symfony/expression-language": "^6.4|^7.0|^8.0", - "symfony/http-foundation": "^6.4|^7.0|^8.0", - "symfony/ldap": "^6.4|^7.0|^8.0", - "symfony/string": "^6.4|^7.0|^8.0", - "symfony/translation": "^6.4.3|^7.0.3|^8.0", - "symfony/validator": "^6.4|^7.0|^8.0", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/http-foundation": "<6.4", - "symfony/ldap": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", - "symfony/validator": "<6.4" + "psr/log": "^1|^2|^3", + "symfony/cache": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/ldap": "^7.4|^8.0", + "symfony/string": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Security\\Core\\": "" }, From 8e0860cbb5c312cd481888617344283f7937554e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Jun 2025 17:41:25 +0200 Subject: [PATCH 3/8] Remove deadcode after the bump to PHP >= 8.4 --- Authentication/Token/NullToken.php | 3 --- Tests/User/InMemoryUserTest.php | 2 +- User/InMemoryUser.php | 3 --- User/OidcUser.php | 3 --- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Authentication/Token/NullToken.php b/Authentication/Token/NullToken.php index cb2bc0fd..9eee0909 100644 --- a/Authentication/Token/NullToken.php +++ b/Authentication/Token/NullToken.php @@ -49,9 +49,6 @@ public function getUserIdentifier(): string #[\Deprecated(since: 'symfony/security-core 7.3')] public function eraseCredentials(): void { - if (\PHP_VERSION_ID < 80400) { - @trigger_error(\sprintf('Method %s::eraseCredentials() is deprecated since symfony/security-core 7.3', self::class), \E_USER_DEPRECATED); - } } public function getAttributes(): array diff --git a/Tests/User/InMemoryUserTest.php b/Tests/User/InMemoryUserTest.php index f06e98c3..7cec7502 100644 --- a/Tests/User/InMemoryUserTest.php +++ b/Tests/User/InMemoryUserTest.php @@ -62,7 +62,7 @@ public function testIsEnabled() public function testEraseCredentials() { $user = new InMemoryUser('fabien', 'superpass'); - $this->expectUserDeprecationMessage(\sprintf('%sMethod %s::eraseCredentials() is deprecated since symfony/security-core 7.3', \PHP_VERSION_ID >= 80400 ? 'Unsilenced deprecation: ' : '', InMemoryUser::class)); + $this->expectUserDeprecationMessage(\sprintf('Unsilenced deprecation: Method %s::eraseCredentials() is deprecated since symfony/security-core 7.3', InMemoryUser::class)); $user->eraseCredentials(); $this->assertEquals('superpass', $user->getPassword()); } diff --git a/User/InMemoryUser.php b/User/InMemoryUser.php index 7bed183a..95543501 100644 --- a/User/InMemoryUser.php +++ b/User/InMemoryUser.php @@ -80,9 +80,6 @@ public function isEnabled(): bool #[\Deprecated(since: 'symfony/security-core 7.3')] public function eraseCredentials(): void { - if (\PHP_VERSION_ID < 80400) { - @trigger_error(\sprintf('Method %s::eraseCredentials() is deprecated since symfony/security-core 7.3', self::class), \E_USER_DEPRECATED); - } } public function isEqualTo(UserInterface $user): bool diff --git a/User/OidcUser.php b/User/OidcUser.php index df59c5f7..08692869 100644 --- a/User/OidcUser.php +++ b/User/OidcUser.php @@ -77,9 +77,6 @@ public function getUserIdentifier(): string #[\Deprecated(since: 'symfony/security-core 7.3')] public function eraseCredentials(): void { - if (\PHP_VERSION_ID < 80400) { - @trigger_error(\sprintf('Method %s::eraseCredentials() is deprecated since symfony/security-core 7.3', self::class), \E_USER_DEPRECATED); - } } public function getSub(): ?string From e666bc317b2be8ef5cff095a2f1f60002ee6de3d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Jun 2025 18:31:05 +0200 Subject: [PATCH 4/8] Enforce return types on all components --- .../RememberMe/TokenProviderInterface.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Authentication/RememberMe/TokenProviderInterface.php b/Authentication/RememberMe/TokenProviderInterface.php index bfe49015..00e8bac5 100644 --- a/Authentication/RememberMe/TokenProviderInterface.php +++ b/Authentication/RememberMe/TokenProviderInterface.php @@ -23,32 +23,24 @@ interface TokenProviderInterface /** * Loads the active token for the given series. * - * @return PersistentTokenInterface - * * @throws TokenNotFoundException if the token is not found */ - public function loadTokenBySeries(string $series); + public function loadTokenBySeries(string $series): PersistentTokenInterface; /** * Deletes all tokens belonging to series. - * - * @return void */ - public function deleteTokenBySeries(string $series); + public function deleteTokenBySeries(string $series): void; /** * Updates the token according to this data. * - * @return void - * * @throws TokenNotFoundException if the token is not found */ - public function updateToken(string $series, #[\SensitiveParameter] string $tokenValue, \DateTimeInterface $lastUsed); + public function updateToken(string $series, #[\SensitiveParameter] string $tokenValue, \DateTimeInterface $lastUsed): void; /** * Creates a new token. - * - * @return void */ - public function createNewToken(PersistentTokenInterface $token); + public function createNewToken(PersistentTokenInterface $token): void; } From 4f1b0a73633657db109415e29d1366d3e69863a8 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 8 Jun 2025 19:33:20 +0200 Subject: [PATCH 5/8] [Security][Ldap] Remove deprecated `eraseCredentials()` from (User|Token)Interface --- Authentication/Token/AbstractToken.php | 14 -------------- Authentication/Token/NullToken.php | 8 -------- Authentication/Token/TokenInterface.php | 7 ------- CHANGELOG.md | 6 ++++++ .../AuthenticationTrustResolverTest.php | 5 ----- Tests/Authentication/Token/AbstractTokenTest.php | 16 ---------------- .../Authentication/Token/Fixtures/CustomUser.php | 5 ----- Tests/User/InMemoryUserTest.php | 11 ----------- User/InMemoryUser.php | 8 -------- User/OAuth2User.php | 4 ---- User/OidcUser.php | 8 -------- User/UserInterface.php | 10 ---------- 12 files changed, 6 insertions(+), 96 deletions(-) diff --git a/Authentication/Token/AbstractToken.php b/Authentication/Token/AbstractToken.php index 683e46d4..aa03ab7d 100644 --- a/Authentication/Token/AbstractToken.php +++ b/Authentication/Token/AbstractToken.php @@ -55,20 +55,6 @@ public function setUser(UserInterface $user): void $this->user = $user; } - /** - * Removes sensitive information from the token. - * - * @deprecated since Symfony 7.3, erase credentials using the "__serialize()" method instead - */ - public function eraseCredentials(): void - { - trigger_deprecation('symfony/security-core', '7.3', \sprintf('The "%s::eraseCredentials()" method is deprecated and will be removed in 8.0, erase credentials using the "__serialize()" method instead.', TokenInterface::class)); - - if ($this->getUser() instanceof UserInterface) { - $this->getUser()->eraseCredentials(); - } - } - /** * Returns all the necessary state of the object for serialization purposes. * diff --git a/Authentication/Token/NullToken.php b/Authentication/Token/NullToken.php index 9eee0909..2e35f0ef 100644 --- a/Authentication/Token/NullToken.php +++ b/Authentication/Token/NullToken.php @@ -43,14 +43,6 @@ public function getUserIdentifier(): string return ''; } - /** - * @deprecated since Symfony 7.3 - */ - #[\Deprecated(since: 'symfony/security-core 7.3')] - public function eraseCredentials(): void - { - } - public function getAttributes(): array { return []; diff --git a/Authentication/Token/TokenInterface.php b/Authentication/Token/TokenInterface.php index c658e38b..80423774 100644 --- a/Authentication/Token/TokenInterface.php +++ b/Authentication/Token/TokenInterface.php @@ -57,13 +57,6 @@ public function getUser(): ?UserInterface; */ public function setUser(UserInterface $user): void; - /** - * Removes sensitive information from the token. - * - * @deprecated since Symfony 7.3; erase credentials using the "__serialize()" method instead - */ - public function eraseCredentials(): void; - public function getAttributes(): array; /** diff --git a/CHANGELOG.md b/CHANGELOG.md index 12806416..29f22013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +8.0 +--- + + * Remove `UserInterface::eraseCredentials()` and `TokenInterface::eraseCredentials()`, + erase credentials e.g. using `__serialize()` instead + 7.3 --- diff --git a/Tests/Authentication/AuthenticationTrustResolverTest.php b/Tests/Authentication/AuthenticationTrustResolverTest.php index c657b31e..74d1cac9 100644 --- a/Tests/Authentication/AuthenticationTrustResolverTest.php +++ b/Tests/Authentication/AuthenticationTrustResolverTest.php @@ -119,11 +119,6 @@ public function getUserIdentifier(): string { } - #[\Deprecated] - public function eraseCredentials(): void - { - } - public function getAttributes(): array { } diff --git a/Tests/Authentication/Token/AbstractTokenTest.php b/Tests/Authentication/Token/AbstractTokenTest.php index 3972b1cd..4966414d 100644 --- a/Tests/Authentication/Token/AbstractTokenTest.php +++ b/Tests/Authentication/Token/AbstractTokenTest.php @@ -37,22 +37,6 @@ public static function provideUsers() yield [new InMemoryUser('fabien', null), 'fabien']; } - /** - * @group legacy - */ - public function testEraseCredentials() - { - $token = new ConcreteToken(['ROLE_FOO']); - - $user = $this->createMock(UserInterface::class); - $user->expects($this->once())->method('eraseCredentials'); - $token->setUser($user); - - $this->expectUserDeprecationMessage(\sprintf('Since symfony/security-core 7.3: The "%s::eraseCredentials()" method is deprecated and will be removed in 8.0, erase credentials using the "__serialize()" method instead.', TokenInterface::class)); - - $token->eraseCredentials(); - } - public function testSerialize() { $token = new ConcreteToken(['ROLE_FOO', 'ROLE_BAR']); diff --git a/Tests/Authentication/Token/Fixtures/CustomUser.php b/Tests/Authentication/Token/Fixtures/CustomUser.php index d4f91de1..388e38c6 100644 --- a/Tests/Authentication/Token/Fixtures/CustomUser.php +++ b/Tests/Authentication/Token/Fixtures/CustomUser.php @@ -35,9 +35,4 @@ public function getPassword(): ?string { return null; } - - #[\Deprecated] - public function eraseCredentials(): void - { - } } diff --git a/Tests/User/InMemoryUserTest.php b/Tests/User/InMemoryUserTest.php index 7cec7502..8b4da62b 100644 --- a/Tests/User/InMemoryUserTest.php +++ b/Tests/User/InMemoryUserTest.php @@ -56,17 +56,6 @@ public function testIsEnabled() $this->assertFalse($user->isEnabled()); } - /** - * @group legacy - */ - public function testEraseCredentials() - { - $user = new InMemoryUser('fabien', 'superpass'); - $this->expectUserDeprecationMessage(\sprintf('Unsilenced deprecation: Method %s::eraseCredentials() is deprecated since symfony/security-core 7.3', InMemoryUser::class)); - $user->eraseCredentials(); - $this->assertEquals('superpass', $user->getPassword()); - } - public function testToString() { $user = new InMemoryUser('fabien', 'superpass'); diff --git a/User/InMemoryUser.php b/User/InMemoryUser.php index 95543501..85f4aa5c 100644 --- a/User/InMemoryUser.php +++ b/User/InMemoryUser.php @@ -74,14 +74,6 @@ public function isEnabled(): bool return $this->enabled; } - /** - * @deprecated since Symfony 7.3 - */ - #[\Deprecated(since: 'symfony/security-core 7.3')] - public function eraseCredentials(): void - { - } - public function isEqualTo(UserInterface $user): bool { if (!$user instanceof self) { diff --git a/User/OAuth2User.php b/User/OAuth2User.php index 42c0550a..8ee5e931 100644 --- a/User/OAuth2User.php +++ b/User/OAuth2User.php @@ -63,8 +63,4 @@ public function getUserIdentifier(): string { return (string) ($this->sub ?? $this->username); } - - public function eraseCredentials(): void - { - } } diff --git a/User/OidcUser.php b/User/OidcUser.php index 08692869..d61cb943 100644 --- a/User/OidcUser.php +++ b/User/OidcUser.php @@ -71,14 +71,6 @@ public function getUserIdentifier(): string return (string) ($this->userIdentifier ?? $this->getSub()); } - /** - * @deprecated since Symfony 7.3 - */ - #[\Deprecated(since: 'symfony/security-core 7.3')] - public function eraseCredentials(): void - { - } - public function getSub(): ?string { return $this->sub; diff --git a/User/UserInterface.php b/User/UserInterface.php index 24c0581f..3d01475e 100644 --- a/User/UserInterface.php +++ b/User/UserInterface.php @@ -47,16 +47,6 @@ interface UserInterface */ public function getRoles(): array; - /** - * Removes sensitive data from the user. - * - * This is important if, at any given point, sensitive information like - * the plain-text password is stored on this object. - * - * @deprecated since Symfony 7.3, erase credentials using the "__serialize()" method instead - */ - public function eraseCredentials(): void; - /** * Returns the identifier for this user (e.g. username or email address). * From f90d78b84cdd61498c624c1c9f4314609a5438e7 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 9 Jun 2025 12:37:44 +0200 Subject: [PATCH 6/8] deprecate handling options in the base Constraint class --- Tests/Validator/Constraints/UserPasswordTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Tests/Validator/Constraints/UserPasswordTest.php b/Tests/Validator/Constraints/UserPasswordTest.php index ed4ca442..2c990808 100644 --- a/Tests/Validator/Constraints/UserPasswordTest.php +++ b/Tests/Validator/Constraints/UserPasswordTest.php @@ -35,8 +35,6 @@ public function testValidatedByService(UserPassword $constraint) public static function provideServiceValidatedConstraints(): iterable { - yield 'Doctrine style' => [new UserPassword(['service' => 'my_service'])]; - yield 'named arguments' => [new UserPassword(service: 'my_service')]; $metadata = new ClassMetadata(UserPasswordDummy::class); @@ -45,6 +43,14 @@ public static function provideServiceValidatedConstraints(): iterable yield 'attribute' => [$metadata->properties['b']->constraints[0]]; } + /** + * @group legacy + */ + public function testValidatedByServiceDoctrineStyle() + { + self::assertSame('my_service', (new UserPassword(['service' => 'my_service']))->validatedBy()); + } + public function testAttributes() { $metadata = new ClassMetadata(UserPasswordDummy::class); From c374c9645b3484de77b471832c0e5771c19a2411 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Jul 2025 11:08:29 +0200 Subject: [PATCH 7/8] Various CS fixes --- Authentication/Token/AbstractToken.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Authentication/Token/AbstractToken.php b/Authentication/Token/AbstractToken.php index 683e46d4..d730c111 100644 --- a/Authentication/Token/AbstractToken.php +++ b/Authentication/Token/AbstractToken.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Security\Core\Authentication\Token; -use Symfony\Component\Security\Core\User\EquatableInterface; use Symfony\Component\Security\Core\User\InMemoryUser; use Symfony\Component\Security\Core\User\UserInterface; From 4e32ac1fd40278269d295d7608fa954f3fb0b483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20TH=C3=89RAGE?= Date: Tue, 1 Jul 2025 11:44:02 +0200 Subject: [PATCH 8/8] [Security] Remove deprecated `RememberMeToken::getSecret()` --- Authentication/Token/RememberMeToken.php | 22 ++----------------- CHANGELOG.md | 1 + .../Token/RememberMeTokenTest.php | 11 ---------- composer.json | 1 - 4 files changed, 3 insertions(+), 32 deletions(-) diff --git a/Authentication/Token/RememberMeToken.php b/Authentication/Token/RememberMeToken.php index dfbe20ec..e9bca720 100644 --- a/Authentication/Token/RememberMeToken.php +++ b/Authentication/Token/RememberMeToken.php @@ -21,8 +21,6 @@ */ class RememberMeToken extends AbstractToken { - private ?string $secret = null; - /** * @throws \InvalidArgumentException */ @@ -32,11 +30,6 @@ public function __construct( ) { parent::__construct($user->getRoles()); - if (\func_num_args() > 2) { - trigger_deprecation('symfony/security-core', '7.2', 'The "$secret" argument of "%s()" is deprecated.', __METHOD__); - $this->secret = func_get_arg(2); - } - if (!$firewallName) { throw new InvalidArgumentException('$firewallName must not be empty.'); } @@ -49,25 +42,14 @@ public function getFirewallName(): string return $this->firewallName; } - /** - * @deprecated since Symfony 7.2 - */ - public function getSecret(): string - { - trigger_deprecation('symfony/security-core', '7.2', 'The "%s()" method is deprecated.', __METHOD__); - - return $this->secret ??= base64_encode(random_bytes(8)); - } - public function __serialize(): array { - // $this->firewallName should be kept at index 1 for compatibility with payloads generated before Symfony 8 - return [$this->secret, $this->firewallName, parent::__serialize()]; + return [null, $this->firewallName, parent::__serialize()]; } public function __unserialize(array $data): void { - [$this->secret, $this->firewallName, $parentData] = $data; + [, $this->firewallName, $parentData] = $data; $parentData = \is_array($parentData) ? $parentData : unserialize($parentData); parent::__unserialize($parentData); } diff --git a/CHANGELOG.md b/CHANGELOG.md index 29f22013..5d48dfa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 8.0 --- + * Remove `RememberMeToken::getSecret()` * Remove `UserInterface::eraseCredentials()` and `TokenInterface::eraseCredentials()`, erase credentials e.g. using `__serialize()` instead diff --git a/Tests/Authentication/Token/RememberMeTokenTest.php b/Tests/Authentication/Token/RememberMeTokenTest.php index b0cdbaf1..07f7674e 100644 --- a/Tests/Authentication/Token/RememberMeTokenTest.php +++ b/Tests/Authentication/Token/RememberMeTokenTest.php @@ -27,17 +27,6 @@ public function testConstructor() $this->assertSame($user, $token->getUser()); } - /** - * @group legacy - */ - public function testSecret() - { - $user = $this->getUser(); - $token = new RememberMeToken($user, 'fookey', 'foo'); - - $this->assertEquals('foo', $token->getSecret()); - } - protected function getUser($roles = ['ROLE_FOO']) { $user = $this->createMock(UserInterface::class); diff --git a/composer.json b/composer.json index 2cb894cf..fdee3efa 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.4", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", "symfony/password-hasher": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3"