Skip to content

Commit b92aae3

Browse files
[Security] Unset token roles when serializing it and user implements EquatableInterface
1 parent 5cab1e1 commit b92aae3

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Security\Core\Authentication\Token;
1313

14+
use Symfony\Component\Security\Core\User\EquatableInterface;
1415
use Symfony\Component\Security\Core\User\InMemoryUser;
1516
use Symfony\Component\Security\Core\User\UserInterface;
1617

@@ -23,24 +24,24 @@
2324
abstract class AbstractToken implements TokenInterface, \Serializable
2425
{
2526
private ?UserInterface $user = null;
26-
private array $roleNames = [];
27+
private array $roleNames;
2728
private array $attributes = [];
2829

2930
/**
3031
* @param string[] $roles An array of roles
31-
*
32-
* @throws \InvalidArgumentException
3332
*/
3433
public function __construct(array $roles = [])
3534
{
35+
$this->roleNames = [];
36+
3637
foreach ($roles as $role) {
37-
$this->roleNames[] = $role;
38+
$this->roleNames[] = (string) $role;
3839
}
3940
}
4041

4142
public function getRoleNames(): array
4243
{
43-
return $this->roleNames;
44+
return $this->roleNames ??= self::__construct($this->user->getRoles()) ?? $this->roleNames;
4445
}
4546

4647
public function getUserIdentifier(): string
@@ -82,7 +83,13 @@ public function eraseCredentials(): void
8283
*/
8384
public function __serialize(): array
8485
{
85-
return [$this->user, true, null, $this->attributes, $this->roleNames];
86+
$data = [$this->user, true, null, $this->attributes];
87+
88+
if (!$this->user instanceof EquatableInterface) {
89+
$data[] = $this->roleNames;
90+
}
91+
92+
return $data;
8693
}
8794

8895
/**
@@ -103,7 +110,12 @@ public function __serialize(): array
103110
*/
104111
public function __unserialize(array $data): void
105112
{
106-
[$user, , , $this->attributes, $this->roleNames] = $data;
113+
[$user, , , $this->attributes] = $data;
114+
115+
if (\array_key_exists(4, $data)) {
116+
$this->roleNames = $data[4];
117+
}
118+
107119
$this->user = \is_string($user) ? new InMemoryUser($user, '', $this->roleNames, false) : $user;
108120
}
109121

src/Symfony/Component/Security/Core/Tests/Exception/CustomUserMessageAuthenticationExceptionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public function testSharedSerializedData()
5353
$exception->setSafeMessage('message', ['token' => $token]);
5454

5555
$processed = unserialize(serialize($exception));
56+
$this->assertSame($token->getRoleNames(), $processed->getToken()->getRoleNames());
5657
$this->assertEquals($token, $processed->getToken());
5758
$this->assertEquals($token, $processed->getMessageData()['token']);
5859
$this->assertSame($processed->getToken(), $processed->getMessageData()['token']);
@@ -67,6 +68,7 @@ public function testSharedSerializedDataFromChild()
6768
$exception->setToken($token);
6869

6970
$processed = unserialize(serialize($exception));
71+
$this->assertSame($token->getRoleNames(), $processed->getToken()->getRoleNames());
7072
$this->assertEquals($token, $processed->childMember);
7173
$this->assertEquals($token, $processed->getToken());
7274
$this->assertSame($processed->getToken(), $processed->childMember);

src/Symfony/Component/Security/Http/Firewall/ContextListener.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,12 @@ private static function hasUserChanged(UserInterface $originalUser, TokenInterfa
301301
}
302302
}
303303

304-
$userRoles = array_map('strval', $refreshedUser->getRoles());
304+
$refreshedUserRoles = array_map('strval', $refreshedUser->getRoles());
305+
$originalUserRoles = $refreshedToken->getRoleNames(); // This comes from cloning the original token, so it still contains the roles of the original user
305306

306307
if (
307-
\count($userRoles) !== \count($refreshedToken->getRoleNames())
308-
|| \count($userRoles) !== \count(array_intersect($userRoles, $refreshedToken->getRoleNames()))
308+
\count($refreshedUserRoles) !== \count($originalUserRoles)
309+
|| \count($refreshedUserRoles) !== \count(array_intersect($refreshedUserRoles, $originalUserRoles))
309310
) {
310311
return true;
311312
}

0 commit comments

Comments
 (0)