Fixed entry point resolving and guard entry point configuration
This commit is contained in:
parent
c30d6f9e38
commit
6870a18803
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
|
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
|
||||||
|
|
||||||
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
|
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
|
||||||
|
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
@ -118,10 +119,8 @@ class GuardAuthenticationFactory implements SecurityFactoryInterface, Authentica
|
|||||||
try {
|
try {
|
||||||
return $this->determineEntryPoint(null, $config);
|
return $this->determineEntryPoint(null, $config);
|
||||||
} catch (\LogicException $e) {
|
} catch (\LogicException $e) {
|
||||||
// ignore the exception, the new system prefers setting "entry_point" over "guard.entry_point"
|
throw new InvalidConfigurationException(sprintf('Because you have multiple guard authenticators, you need to set the "entry_point" key to one of your authenticators (%s).', implode(', ', $config['authenticators'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function determineEntryPoint(?string $defaultEntryPointId, array $config): string
|
private function determineEntryPoint(?string $defaultEntryPointId, array $config): string
|
||||||
|
@ -33,6 +33,7 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
|||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\Ldap\Entry;
|
||||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||||
use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder;
|
use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder;
|
||||||
use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
|
use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
|
||||||
@ -443,6 +444,9 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
if (!$this->authenticatorManagerEnabled) {
|
if (!$this->authenticatorManagerEnabled) {
|
||||||
$authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders);
|
$authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders);
|
||||||
} else {
|
} else {
|
||||||
|
// $configuredEntryPoint is resolved into a service ID and stored in $defaultEntryPoint
|
||||||
|
$configuredEntryPoint = $defaultEntryPoint;
|
||||||
|
|
||||||
// authenticator manager
|
// authenticator manager
|
||||||
$authenticators = array_map(function ($id) {
|
$authenticators = array_map(function ($id) {
|
||||||
return new Reference($id);
|
return new Reference($id);
|
||||||
@ -543,7 +547,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
$authenticationProviders[] = $authenticators;
|
$authenticationProviders[] = $authenticators;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($factory instanceof EntryPointFactoryInterface && ($entryPoint = $factory->createEntryPoint($container, $id, $firewall[$key], null))) {
|
if ($factory instanceof EntryPointFactoryInterface && ($entryPoint = $factory->createEntryPoint($container, $id, $firewall[$key]))) {
|
||||||
$entryPoints[$key] = $entryPoint;
|
$entryPoints[$key] = $entryPoint;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,11 +16,19 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
|
|||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
|
||||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||||
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
|
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FirewallEntryPointBundle\Security\EntryPointStub;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AppCustomAuthenticator;
|
||||||
|
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||||
|
use Symfony\Component\Security\Guard\AuthenticatorInterface;
|
||||||
|
|
||||||
class SecurityExtensionTest extends TestCase
|
class SecurityExtensionTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -413,6 +421,90 @@ class SecurityExtensionTest extends TestCase
|
|||||||
$this->assertEquals(new Reference('security.user.provider.concrete.second'), $container->getDefinition('security.authentication.switchuser_listener.foobar')->getArgument(1));
|
$this->assertEquals(new Reference('security.user.provider.concrete.second'), $container->getDefinition('security.authentication.switchuser_listener.foobar')->getArgument(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEntryPointFirewalls
|
||||||
|
*/
|
||||||
|
public function testAuthenticatorManagerEnabledEntryPoint(array $firewall, $entryPointId)
|
||||||
|
{
|
||||||
|
$container = $this->getRawContainer();
|
||||||
|
$container->loadFromExtension('security', [
|
||||||
|
'enable_authenticator_manager' => true,
|
||||||
|
'providers' => [
|
||||||
|
'first' => ['id' => 'users'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'firewalls' => [
|
||||||
|
'main' => $firewall,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$this->assertEquals($entryPointId, (string) $container->getDefinition('security.firewall.map.config.main')->getArgument(7));
|
||||||
|
$this->assertEquals($entryPointId, (string) $container->getDefinition('security.exception_listener.main')->getArgument(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideEntryPointFirewalls()
|
||||||
|
{
|
||||||
|
// only one entry point available
|
||||||
|
yield [['http_basic' => true], 'security.authentication.basic_entry_point.main'];
|
||||||
|
// explicitly configured by authenticator key
|
||||||
|
yield [['form_login' => true, 'http_basic' => true, 'entry_point' => 'form_login'], 'security.authentication.form_entry_point.main'];
|
||||||
|
// explicitly configured another service
|
||||||
|
yield [['form_login' => true, 'entry_point' => EntryPointStub::class], EntryPointStub::class];
|
||||||
|
// no entry point required
|
||||||
|
yield [['json_login' => true], null];
|
||||||
|
|
||||||
|
// only one guard authenticator entry point available
|
||||||
|
yield [[
|
||||||
|
'guard' => ['authenticators' => [AppCustomAuthenticator::class]],
|
||||||
|
], AppCustomAuthenticator::class];
|
||||||
|
// explicitly configured guard authenticator entry point
|
||||||
|
yield [[
|
||||||
|
'guard' => [
|
||||||
|
'authenticators' => [AppCustomAuthenticator::class, NullAuthenticator::class],
|
||||||
|
'entry_point' => NullAuthenticator::class,
|
||||||
|
],
|
||||||
|
], NullAuthenticator::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEntryPointRequiredData
|
||||||
|
*/
|
||||||
|
public function testEntryPointRequired(array $firewall, $messageRegex)
|
||||||
|
{
|
||||||
|
$this->expectException(InvalidConfigurationException::class);
|
||||||
|
$this->expectExceptionMessageMatches($messageRegex);
|
||||||
|
|
||||||
|
$container = $this->getRawContainer();
|
||||||
|
$container->loadFromExtension('security', [
|
||||||
|
'enable_authenticator_manager' => true,
|
||||||
|
'providers' => [
|
||||||
|
'first' => ['id' => 'users'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'firewalls' => [
|
||||||
|
'main' => $firewall,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideEntryPointRequiredData()
|
||||||
|
{
|
||||||
|
// more than one entry point available and not explicitly set
|
||||||
|
yield [
|
||||||
|
['http_basic' => true, 'form_login' => true],
|
||||||
|
'/^Because you have multiple authenticators in firewall "main", you need to set the "entry_point" key to one of your authenticators/',
|
||||||
|
];
|
||||||
|
// more than one guard entry point available and not explicitly set
|
||||||
|
yield [
|
||||||
|
['guard' => ['authenticators' => [AppCustomAuthenticator::class, NullAuthenticator::class]]],
|
||||||
|
'/^Because you have multiple guard authenticators, you need to set the "entry_point" key to one of your authenticators/',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
protected function getRawContainer()
|
protected function getRawContainer()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
@ -439,3 +531,42 @@ class SecurityExtensionTest extends TestCase
|
|||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NullAuthenticator implements AuthenticatorInterface
|
||||||
|
{
|
||||||
|
public function start(Request $request, AuthenticationException $authException = null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supports(Request $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCredentials(Request $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser($credentials, UserProviderInterface $userProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkCredentials($credentials, UserInterface $user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createAuthenticatedToken(UserInterface $user, string $providerKey)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsRememberMe()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"php": "^7.2.5",
|
"php": "^7.2.5",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"symfony/config": "^4.4|^5.0",
|
"symfony/config": "^4.4|^5.0",
|
||||||
"symfony/dependency-injection": "^4.4|^5.0",
|
"symfony/dependency-injection": "^5.1",
|
||||||
"symfony/event-dispatcher": "^5.1",
|
"symfony/event-dispatcher": "^5.1",
|
||||||
"symfony/http-kernel": "^5.0",
|
"symfony/http-kernel": "^5.0",
|
||||||
"symfony/polyfill-php80": "^1.15",
|
"symfony/polyfill-php80": "^1.15",
|
||||||
|
Reference in New Issue
Block a user