Skip to content

Commit 95dce67

Browse files
watashi-djoRobin Chalas
authored and
Robin Chalas
committed
[Security] Do not deauthenticate user when the first refreshed user has changed
1 parent 4081bc6 commit 95dce67

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

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

+18-4
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ protected function refreshUser(TokenInterface $token)
161161
}
162162

163163
$userNotFoundByProvider = false;
164+
$userDeauthenticated = false;
164165

165166
foreach ($this->userProviders as $provider) {
166167
if (!$provider instanceof UserProviderInterface) {
@@ -169,21 +170,26 @@ protected function refreshUser(TokenInterface $token)
169170

170171
try {
171172
$refreshedUser = $provider->refreshUser($user);
172-
$token->setUser($refreshedUser);
173+
$newToken = unserialize(serialize($token));
174+
$newToken->setUser($refreshedUser);
173175

174176
// tokens can be deauthenticated if the user has been changed.
175-
if (!$token->isAuthenticated()) {
177+
if (!$newToken->isAuthenticated()) {
176178
if ($this->logoutOnUserChange) {
179+
$userDeauthenticated = true;
180+
177181
if (null !== $this->logger) {
178-
$this->logger->debug('Token was deauthenticated after trying to refresh it.', array('username' => $refreshedUser->getUsername(), 'provider' => \get_class($provider)));
182+
$this->logger->debug('Cannot refresh token because user has changed.', array('username' => $refreshedUser->getUsername(), 'provider' => \get_class($provider)));
179183
}
180184

181-
return null;
185+
continue;
182186
}
183187

184188
@trigger_error('Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0.', E_USER_DEPRECATED);
185189
}
186190

191+
$token->setUser($refreshedUser);
192+
187193
if (null !== $this->logger) {
188194
$context = array('provider' => \get_class($provider), 'username' => $refreshedUser->getUsername());
189195

@@ -209,6 +215,14 @@ protected function refreshUser(TokenInterface $token)
209215
}
210216
}
211217

218+
if ($userDeauthenticated) {
219+
if (null !== $this->logger) {
220+
$this->logger->debug('Token was deauthenticated after trying to refresh it.');
221+
}
222+
223+
return null;
224+
}
225+
212226
if ($userNotFoundByProvider) {
213227
return null;
214228
}

src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ public function testIfTokenIsDeauthenticated()
273273
$this->assertNull($tokenStorage->getToken());
274274
}
275275

276+
public function testIfTokenIsNotDeauthenticated()
277+
{
278+
$tokenStorage = new TokenStorage();
279+
$badRefreshedUser = new User('foobar', 'baz');
280+
$goodRefreshedUser = new User('foobar', 'bar');
281+
$this->handleEventWithPreviousSession($tokenStorage, array(new SupportingUserProvider($badRefreshedUser), new SupportingUserProvider($goodRefreshedUser)), $goodRefreshedUser, true);
282+
$this->assertSame($goodRefreshedUser, $tokenStorage->getToken()->getUser());
283+
}
284+
276285
public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
277286
{
278287
$tokenStorage = new TokenStorage();

0 commit comments

Comments
 (0)