Skip to content

Commit 575fe1a

Browse files
biomedia-thomasnicolas-grekas
authored andcommitted
[Security] guardAuthenticationProvider::authenticate cannot return null according to interface specification
1 parent 4057067 commit 575fe1a

File tree

2 files changed

+68
-11
lines changed

2 files changed

+68
-11
lines changed

src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
1515
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
16+
use Symfony\Component\Security\Core\Exception\AuthenticationException;
1617
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
1718
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
1819
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
@@ -63,7 +64,7 @@ public function __construct(array $guardAuthenticators, UserProviderInterface $u
6364
*/
6465
public function authenticate(TokenInterface $token)
6566
{
66-
if (!$this->supports($token)) {
67+
if (!$token instanceof GuardTokenInterface) {
6768
throw new \InvalidArgumentException('GuardAuthenticationProvider only supports GuardTokenInterface.');
6869
}
6970

@@ -87,19 +88,17 @@ public function authenticate(TokenInterface $token)
8788
throw new AuthenticationExpiredException();
8889
}
8990

90-
// find the *one* GuardAuthenticator that this token originated from
91-
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
92-
// get a key that's unique to *this* guard authenticator
93-
// this MUST be the same as GuardAuthenticationListener
94-
$uniqueGuardKey = $this->providerKey.'_'.$key;
91+
$guardAuthenticator = $this->findOriginatingAuthenticator($token);
9592

96-
if ($uniqueGuardKey == $token->getGuardProviderKey()) {
97-
return $this->authenticateViaGuard($guardAuthenticator, $token);
98-
}
93+
if (null === $guardAuthenticator) {
94+
throw new AuthenticationException(sprintf(
95+
'Token with provider key "%s" did not originate from any of the guard authenticators of provider "%s".',
96+
$token->getGuardProviderKey(),
97+
$this->providerKey
98+
));
9999
}
100100

101-
// no matching authenticator found - but there will be multiple GuardAuthenticationProvider
102-
// instances that will be checked if you have multiple firewalls.
101+
return $this->authenticateViaGuard($guardAuthenticator, $token);
103102
}
104103

105104
private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token)
@@ -141,8 +140,31 @@ private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenti
141140
return $authenticatedToken;
142141
}
143142

143+
private function findOriginatingAuthenticator(PreAuthenticationGuardToken $token)
144+
{
145+
// find the *one* GuardAuthenticator that this token originated from
146+
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
147+
// get a key that's unique to *this* guard authenticator
148+
// this MUST be the same as GuardAuthenticationListener
149+
$uniqueGuardKey = $this->providerKey.'_'.$key;
150+
151+
if ($uniqueGuardKey === $token->getGuardProviderKey()) {
152+
return $guardAuthenticator;
153+
}
154+
}
155+
156+
// no matching authenticator found - but there will be multiple GuardAuthenticationProvider
157+
// instances that will be checked if you have multiple firewalls.
158+
159+
return null;
160+
}
161+
144162
public function supports(TokenInterface $token)
145163
{
164+
if ($token instanceof PreAuthenticationGuardToken) {
165+
return null !== $this->findOriginatingAuthenticator($token);
166+
}
167+
146168
return $token instanceof GuardTokenInterface;
147169
}
148170
}

src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider;
1616
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
17+
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
1718

1819
/**
1920
* @author Ryan Weaver <weaverryan@gmail.com>
@@ -133,6 +134,40 @@ public function testGuardWithNoLongerAuthenticatedTriggersLogout()
133134
$actualToken = $provider->authenticate($token);
134135
}
135136

137+
public function testSupportsChecksGuardAuthenticatorsTokenOrigin()
138+
{
139+
$authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
140+
$authenticatorB = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
141+
$authenticators = array($authenticatorA, $authenticatorB);
142+
143+
$mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
144+
$provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, 'first_firewall', $this->userChecker);
145+
146+
$token = new PreAuthenticationGuardToken($mockedUser, 'first_firewall_1');
147+
$supports = $provider->supports($token);
148+
$this->assertTrue($supports);
149+
150+
$token = new PreAuthenticationGuardToken($mockedUser, 'second_firewall_0');
151+
$supports = $provider->supports($token);
152+
$this->assertFalse($supports);
153+
}
154+
155+
/**
156+
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
157+
* @expectedExceptionMessageRegExp /second_firewall_0/
158+
*/
159+
public function testAuthenticateFailsOnNonOriginatingToken()
160+
{
161+
$authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
162+
$authenticators = array($authenticatorA);
163+
164+
$mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
165+
$provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, 'first_firewall', $this->userChecker);
166+
167+
$token = new PreAuthenticationGuardToken($mockedUser, 'second_firewall_0');
168+
$provider->authenticate($token);
169+
}
170+
136171
protected function setUp()
137172
{
138173
$this->userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock();

0 commit comments

Comments
 (0)