Skip to content

Commit 76a7fe7

Browse files
committed
feature #42423 [Security] Deprecate AnonymousToken, non-UserInterface users, and token credentials (wouterj)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [Security] Deprecate AnonymousToken, non-UserInterface users, and token credentials | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | no | Deprecations? | yes | Tickets | Ref #41613, #34909 | License | MIT | Doc PR | - This is a continuation of `@xabbuh`'s experiment in #34909 and `@chalasr`'s work in #42050. This hopefully is the last cleanup of `TokenInterface`: * As tokens now always represent an authenticated user (and no longer e.g. the "username" input of the form), we can finally remove the weird `string|\Stringable` union from `Token::getUser()` and other helper methods and require a user to be an instance of `UserInterface`. * For the same reason, we can also deprecate token credentials. I didn't deprecate `Token::eraseCredentials()` as this is still used to remove credentials from `UserInterface`. * Meanwhile, this also deprecated the `AnonymousToken`, which we forgot in 5.3. This token is not used anymore in the new system (anonymous does no longer exists). This was also the only token in core that didn't fulfill the `UserInterface` requirement for authenticated tokens. Commits ------- 44b843a [Security] Deprecate AnonymousToken, non-UserInterface users, and token credentials
2 parents c939ea1 + 44b843a commit 76a7fe7

File tree

47 files changed

+347
-130
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+347
-130
lines changed

UPGRADE-5.4.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ SecurityBundle
5959
Security
6060
--------
6161

62-
* Deprecate the `$authManager` argument of `AccessListener`
63-
* Deprecate the `$authenticationManager` argument of the `AuthorizationChecker` constructor
62+
* Deprecate `AnonymousToken`, as the related authenticator was deprecated in 5.3
63+
* Deprecate `Token::getCredentials()`, tokens should no longer contain credentials (as they represent authenticated sessions)
64+
* Deprecate not returning an `UserInterface` from `Token::getUser()`
65+
* Deprecate the `$authManager` argument of `AccessListener`, the argument will be removed
66+
* Deprecate the `$authenticationManager` argument of the `AuthorizationChecker` constructor, the argument will be removed
6467
* Deprecate setting the `$alwaysAuthenticate` argument to `true` and not setting the
6568
`$exceptionOnNoToken argument to `false` of `AuthorizationChecker` (this is the default
6669
behavior when using `enable_authenticator_manager: true`)

UPGRADE-6.0.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ Routing
207207
Security
208208
--------
209209

210+
* Remove `AnonymousToken`
211+
* Remove `Token::getCredentials()`, tokens should no longer contain credentials (as they represent authenticated sessions)
212+
* Restrict the return type of `Token::getUser()` to `UserInterface` (removing `string|\Stringable`)
210213
* Remove the 4th and 5th argument of `AuthorizationChecker`
211214
* Remove the 5th argument of `AccessListener`
212215
* Remove class `User`, use `InMemoryUser` or your own implementation instead.

src/Symfony/Bridge/Monolog/Tests/Processor/SwitchUserTokenProcessorTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1717
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
1818
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
19+
use Symfony\Component\Security\Core\User\InMemoryUser;
20+
use Symfony\Component\Security\Core\User\User;
1921

2022
/**
2123
* Tests the SwitchUserTokenProcessor.
@@ -26,8 +28,13 @@ class SwitchUserTokenProcessorTest extends TestCase
2628
{
2729
public function testProcessor()
2830
{
29-
$originalToken = new UsernamePasswordToken('original_user', 'password', 'provider', ['ROLE_SUPER_ADMIN']);
30-
$switchUserToken = new SwitchUserToken('user', 'passsword', 'provider', ['ROLE_USER'], $originalToken);
31+
if (class_exists(InMemoryUser::class)) {
32+
$originalToken = new UsernamePasswordToken(new InMemoryUser('original_user', 'password', ['ROLE_SUPER_ADMIN']), 'provider', ['ROLE_SUPER_ADMIN']);
33+
$switchUserToken = new SwitchUserToken(new InMemoryUser('user', 'passsword', ['ROLE_USER']), 'provider', ['ROLE_USER'], $originalToken);
34+
} else {
35+
$originalToken = new UsernamePasswordToken(new User('original_user', 'password', ['ROLE_SUPER_ADMIN']), null, 'provider', ['ROLE_SUPER_ADMIN']);
36+
$switchUserToken = new SwitchUserToken(new User('user', 'passsword', ['ROLE_USER']), null, 'provider', ['ROLE_USER'], $originalToken);
37+
}
3138
$tokenStorage = $this->createMock(TokenStorageInterface::class);
3239
$tokenStorage->method('getToken')->willReturn($switchUserToken);
3340

src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Bridge\Monolog\Processor\TokenProcessor;
1616
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1717
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
18+
use Symfony\Component\Security\Core\User\InMemoryUser;
1819

1920
/**
2021
* Tests the TokenProcessor.
@@ -23,6 +24,9 @@
2324
*/
2425
class TokenProcessorTest extends TestCase
2526
{
27+
/**
28+
* @group legacy
29+
*/
2630
public function testLegacyProcessor()
2731
{
2832
if (method_exists(UsernamePasswordToken::class, 'getUserIdentifier')) {
@@ -48,7 +52,7 @@ public function testProcessor()
4852
$this->markTestSkipped('This test requires symfony/security-core 5.3+');
4953
}
5054

51-
$token = new UsernamePasswordToken('user', 'password', 'provider', ['ROLE_USER']);
55+
$token = new UsernamePasswordToken(new InMemoryUser('user', 'password', ['ROLE_USER']), 'provider', ['ROLE_USER']);
5256
$tokenStorage = $this->createMock(TokenStorageInterface::class);
5357
$tokenStorage->method('getToken')->willReturn($token);
5458

src/Symfony/Bridge/Twig/AppVariable.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public function getUser()
8484

8585
$user = $token->getUser();
8686

87+
// @deprecated since 5.4, $user will always be a UserInterface instance
8788
return \is_object($user) ? $user : null;
8889
}
8990

src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ protected function getDoctrine(): ManagerRegistry
395395
/**
396396
* Get a user from the Security Token Storage.
397397
*
398-
* @return UserInterface|object|null
398+
* @return UserInterface|null
399399
*
400400
* @throws \LogicException If SecurityBundle is not available
401401
*
@@ -411,6 +411,7 @@ protected function getUser()
411411
return null;
412412
}
413413

414+
// @deprecated since 5.4, $user will always be a UserInterface instance
414415
if (!\is_object($user = $token->getUser())) {
415416
// e.g. anonymous authentication
416417
return null;

src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,17 @@ public function testForward()
138138
public function testGetUser()
139139
{
140140
$user = new InMemoryUser('user', 'pass');
141-
$token = new UsernamePasswordToken($user, 'pass', 'default', ['ROLE_USER']);
141+
$token = new UsernamePasswordToken($user, 'default', ['ROLE_USER']);
142142

143143
$controller = $this->createController();
144144
$controller->setContainer($this->getContainerWithTokenStorage($token));
145145

146146
$this->assertSame($controller->getUser(), $user);
147147
}
148148

149+
/**
150+
* @group legacy
151+
*/
149152
public function testGetUserAnonymousUserConvertedToNull()
150153
{
151154
$token = new AnonymousToken('default', 'anon.');

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"symfony/notifier": "^5.3|^6.0",
5454
"symfony/process": "^4.4|^5.0|^6.0",
5555
"symfony/rate-limiter": "^5.2|^6.0",
56-
"symfony/security-bundle": "^5.3|^6.0",
56+
"symfony/security-bundle": "^5.4|^6.0",
5757
"symfony/serializer": "^5.4|^6.0",
5858
"symfony/stopwatch": "^4.4|^5.0|^6.0",
5959
"symfony/string": "^5.0|^6.0",
@@ -89,7 +89,6 @@
8989
"symfony/property-access": "<5.3",
9090
"symfony/serializer": "<5.2",
9191
"symfony/security-csrf": "<5.3",
92-
"symfony/security-core": "<5.3",
9392
"symfony/stopwatch": "<4.4",
9493
"symfony/translation": "<5.3",
9594
"symfony/twig-bridge": "<4.4",

src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter;
3030
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
3131
use Symfony\Component\Security\Core\Role\RoleHierarchy;
32+
use Symfony\Component\Security\Core\User\InMemoryUser;
3233
use Symfony\Component\Security\Http\FirewallMapInterface;
3334
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
3435
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
@@ -78,7 +79,7 @@ public function testCollectWhenAuthenticationTokenIsNull()
7879
public function testCollectAuthenticationTokenAndRoles(array $roles, array $normalizedRoles, array $inheritedRoles)
7980
{
8081
$tokenStorage = new TokenStorage();
81-
$tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $roles));
82+
$tokenStorage->setToken(new UsernamePasswordToken(new InMemoryUser('hhamon', 'P4$$w0rD', $roles), 'provider', $roles));
8283

8384
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy(), null, null, null, null, true);
8485
$collector->collect(new Request(), new Response());
@@ -99,10 +100,10 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm
99100

100101
public function testCollectSwitchUserToken()
101102
{
102-
$adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', ['ROLE_ADMIN']);
103+
$adminToken = new UsernamePasswordToken(new InMemoryUser('yceruto', 'P4$$w0rD', ['ROLE_ADMIN']), 'provider', ['ROLE_ADMIN']);
103104

104105
$tokenStorage = new TokenStorage();
105-
$tokenStorage->setToken(new SwitchUserToken('hhamon', 'P4$$w0rD', 'provider', ['ROLE_USER', 'ROLE_PREVIOUS_ADMIN'], $adminToken));
106+
$tokenStorage->setToken(new SwitchUserToken(new InMemoryUser('hhamon', 'P4$$w0rD', ['ROLE_USER', 'ROLE_PREVIOUS_ADMIN']), 'provider', ['ROLE_USER', 'ROLE_PREVIOUS_ADMIN'], $adminToken));
106107

107108
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy(), null, null, null, null, true);
108109
$collector->collect(new Request(), new Response());

src/Symfony/Bundle/SecurityBundle/Tests/Functional/MissingUserProviderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public function testUserProviderIsNeeded()
2828
]);
2929
}
3030

31+
/**
32+
* @group legacy
33+
*/
3134
public function testLegacyUserProviderIsNeeded()
3235
{
3336
$client = $this->createClient(['test_case' => 'MissingUserProvider', 'root_config' => 'config.yml', 'debug' => true]);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy