diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index e61907eff302..4b99fa7bdbe3 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -153,6 +153,7 @@ protected function refreshUser(TokenInterface $token) $this->logger->debug(sprintf('Reloading user from user provider.')); } + $exceptions = []; foreach ($this->userProviders as $provider) { try { $refreshedUser = $provider->refreshUser($user); @@ -166,11 +167,19 @@ protected function refreshUser(TokenInterface $token) } catch (UnsupportedUserException $unsupported) { // let's try the next user provider } catch (UsernameNotFoundException $notFound) { - if (null !== $this->logger) { - $this->logger->warning(sprintf('Username "%s" could not be found.', $notFound->getUsername())); - } + // let's try the next user provider + $exceptions[] = [$notFound, $provider]; + } + } - return; + // if a UsernameNotFoundException has been thrown, there are providers + // associated with the token, but none able to refresh it + if ($exceptions) { + if (null !== $this->logger) { + foreach ($exceptions as $exception) { + list($notFound, $provider) = $exception; + $this->logger->warning(sprintf('Username "%s" could not be found from "%s" provider.', $notFound->getUsername(), get_class($provider))); + } } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 90af07e86a62..8e6ca8623c0d 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -21,7 +21,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\SecurityContext; +use Symfony\Component\Security\Core\User\InMemoryUserProvider; use Symfony\Component\Security\Http\Firewall\ContextListener; +use Symfony\Component\Security\Tests\Fixtures\Core\SimpleSecurityContext; class ContextListenerTest extends \PHPUnit_Framework_TestCase { @@ -220,6 +222,54 @@ public function testHandleRemovesTokenIfNoPreviousSessionWasFound() $listener->handle($event); } + public function testCanRefreshUserWithIdenticalSupportedProviders() + { + $providers = array( + $provider1 = new InMemoryUserProvider(array( + 'foo' => array(), + )), + $provider2 = new InMemoryUserProvider(array( + 'bar' => array(), + )), + ); + + $session = new Session(new MockArraySessionStorage()); + + /** @var \Symfony\Component\HttpFoundation\Request $request */ + $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + $request->expects($this->any())->method('hasPreviousSession')->will($this->returnValue(true)); + $request->expects($this->any())->method('getSession')->will($this->returnValue($session)); + + $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->any())->method('getRequest')->will($this->returnValue($request)); + + $context = new SimpleSecurityContext(); + + /** + * We are trying to refresh the "foo" user + */ + $user = new UsernamePasswordToken($provider1->loadUserByUsername('foo'), '123456', 'memory'); + $session->set('_security_' . $key = 'key123', serialize($user)); + + $listener = new ContextListener($context, $providers, $key); + $listener->handle($event); + + $this->assertNotNull($context->getToken()); + + /** + * We are trying to refresh the "bar" user + */ + $user = new UsernamePasswordToken($provider2->loadUserByUsername('bar'), '123456', 'memory'); + $session->set('_security_' . $key = 'key123', serialize($user)); + + $listener = new ContextListener($context, $providers, $key); + $listener->handle($event); + + $this->assertNotNull($context->getToken()); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); diff --git a/src/Symfony/Component/Security/Tests/Fixtures/Core/SimpleSecurityContext.php b/src/Symfony/Component/Security/Tests/Fixtures/Core/SimpleSecurityContext.php new file mode 100644 index 000000000000..53104b76d361 --- /dev/null +++ b/src/Symfony/Component/Security/Tests/Fixtures/Core/SimpleSecurityContext.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Tests\Fixtures\Core; + +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\SecurityContextInterface; + +class SimpleSecurityContext implements SecurityContextInterface +{ + protected $token; + + public function getToken() + { + return $this->token; + } + + public function setToken(TokenInterface $token = null) + { + $this->token = $token; + } + + public function isGranted($attributes, $object = null) + { + return true; + } +}