diff --git a/DependencyInjection/MainConfiguration.php b/DependencyInjection/MainConfiguration.php index ba8a987d..83a1e963 100644 --- a/DependencyInjection/MainConfiguration.php +++ b/DependencyInjection/MainConfiguration.php @@ -216,6 +216,11 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->prototype('scalar')->end() ->end() ->booleanNode('security')->defaultTrue()->end() + ->scalarNode('user_checker') + ->defaultValue('security.user_checker') + ->treatNullLike('security.user_checker') + ->info('The UserChecker to use when authenticating users in this firewall.') + ->end() ->scalarNode('request_matcher')->end() ->scalarNode('access_denied_url')->end() ->scalarNode('access_denied_handler')->end() diff --git a/DependencyInjection/Security/Factory/FormLoginFactory.php b/DependencyInjection/Security/Factory/FormLoginFactory.php index b674c47e..ac9523c5 100644 --- a/DependencyInjection/Security/Factory/FormLoginFactory.php +++ b/DependencyInjection/Security/Factory/FormLoginFactory.php @@ -65,6 +65,7 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config, $container ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao')) ->replaceArgument(0, new Reference($userProviderId)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->replaceArgument(2, $id) ; diff --git a/DependencyInjection/Security/Factory/FormLoginLdapFactory.php b/DependencyInjection/Security/Factory/FormLoginLdapFactory.php index c758b32b..026a3d65 100644 --- a/DependencyInjection/Security/Factory/FormLoginLdapFactory.php +++ b/DependencyInjection/Security/Factory/FormLoginLdapFactory.php @@ -30,6 +30,7 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config, $container ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind')) ->replaceArgument(0, new Reference($userProviderId)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->replaceArgument(2, $id) ->replaceArgument(3, new Reference($config['service'])) ->replaceArgument(4, $config['dn_string']) diff --git a/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php b/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php index 23752677..67bdeceb 100644 --- a/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php +++ b/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php @@ -69,6 +69,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, ->replaceArgument(0, $authenticatorReferences) ->replaceArgument(1, new Reference($userProvider)) ->replaceArgument(2, $id) + ->replaceArgument(3, new Reference('security.user_checker.'.$id)) ; // listener diff --git a/DependencyInjection/Security/Factory/HttpBasicFactory.php b/DependencyInjection/Security/Factory/HttpBasicFactory.php index 0b81f800..162ea051 100644 --- a/DependencyInjection/Security/Factory/HttpBasicFactory.php +++ b/DependencyInjection/Security/Factory/HttpBasicFactory.php @@ -29,6 +29,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $container ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao')) ->replaceArgument(0, new Reference($userProvider)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->replaceArgument(2, $id) ; diff --git a/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php b/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php index 23c01305..f2b1695c 100644 --- a/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php +++ b/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php @@ -31,6 +31,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $container ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind')) ->replaceArgument(0, new Reference($userProvider)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->replaceArgument(2, $id) ->replaceArgument(3, new Reference($config['service'])) ->replaceArgument(4, $config['dn_string']) diff --git a/DependencyInjection/Security/Factory/RememberMeFactory.php b/DependencyInjection/Security/Factory/RememberMeFactory.php index 1746a21f..fc008a9f 100644 --- a/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -35,6 +35,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $authProviderId = 'security.authentication.provider.rememberme.'.$id; $container ->setDefinition($authProviderId, new DefinitionDecorator('security.authentication.provider.rememberme')) + ->replaceArgument(0, new Reference('security.user_checker.'.$id)) ->addArgument($config['secret']) ->addArgument($id) ; diff --git a/DependencyInjection/Security/Factory/RemoteUserFactory.php b/DependencyInjection/Security/Factory/RemoteUserFactory.php index 01ac91ce..cf2e2ed7 100644 --- a/DependencyInjection/Security/Factory/RemoteUserFactory.php +++ b/DependencyInjection/Security/Factory/RemoteUserFactory.php @@ -30,6 +30,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $container ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.pre_authenticated')) ->replaceArgument(0, new Reference($userProvider)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->addArgument($id) ; diff --git a/DependencyInjection/Security/Factory/X509Factory.php b/DependencyInjection/Security/Factory/X509Factory.php index f8ca5509..0467ef2b 100644 --- a/DependencyInjection/Security/Factory/X509Factory.php +++ b/DependencyInjection/Security/Factory/X509Factory.php @@ -29,6 +29,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $container ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.pre_authenticated')) ->replaceArgument(0, new Reference($userProvider)) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)) ->addArgument($id) ; diff --git a/DependencyInjection/SecurityExtension.php b/DependencyInjection/SecurityExtension.php index 96bc7cb6..bd0d2959 100644 --- a/DependencyInjection/SecurityExtension.php +++ b/DependencyInjection/SecurityExtension.php @@ -14,6 +14,7 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -100,16 +101,16 @@ public function load(array $configs, ContainerBuilder $container) // add some required classes for compilation $this->addClassesToCompile(array( - 'Symfony\\Component\\Security\\Http\\Firewall', - 'Symfony\\Component\\Security\\Core\\User\\UserProviderInterface', - 'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationProviderManager', - 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorage', - 'Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager', - 'Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker', - 'Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface', - 'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap', - 'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext', - 'Symfony\\Component\\HttpFoundation\\RequestMatcher', + 'Symfony\Component\Security\Http\Firewall', + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager', + 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage', + 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager', + 'Symfony\Component\Security\Core\Authorization\AuthorizationChecker', + 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface', + 'Symfony\Bundle\SecurityBundle\Security\FirewallMap', + 'Symfony\Bundle\SecurityBundle\Security\FirewallContext', + 'Symfony\Component\HttpFoundation\RequestMatcher', )); } @@ -369,6 +370,8 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a // Exception listener $exceptionListener = new Reference($this->createExceptionListener($container, $firewall, $id, $configuredEntryPoint ?: $defaultEntryPoint, $firewall['stateless'])); + $container->setAlias(new Alias('security.user_checker.'.$id, false), $firewall['user_checker']); + return array($matcher, $listeners, $exceptionListener); } @@ -577,6 +580,7 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv $switchUserListenerId = 'security.authentication.switchuser_listener.'.$id; $listener = $container->setDefinition($switchUserListenerId, new DefinitionDecorator('security.authentication.switchuser_listener')); $listener->replaceArgument(1, new Reference($userProvider)); + $listener->replaceArgument(2, new Reference('security.user_checker.'.$id)); $listener->replaceArgument(3, $id); $listener->replaceArgument(6, $config['parameter']); $listener->replaceArgument(7, $config['role']); diff --git a/Resources/config/guard.xml b/Resources/config/guard.xml index 0524cf2b..80318c24 100644 --- a/Resources/config/guard.xml +++ b/Resources/config/guard.xml @@ -21,7 +21,7 @@ - + - + %security.authentication.hide_user_not_found% @@ -180,7 +180,7 @@ - + @@ -195,7 +195,7 @@ - + @@ -215,7 +215,7 @@ - + diff --git a/Resources/config/security_rememberme.xml b/Resources/config/security_rememberme.xml index 083dbcc3..7a0087ef 100644 --- a/Resources/config/security_rememberme.xml +++ b/Resources/config/security_rememberme.xml @@ -16,7 +16,7 @@ - + diff --git a/Tests/DependencyInjection/CompleteConfigurationTest.php b/Tests/DependencyInjection/CompleteConfigurationTest.php index 5a40f191..c6aef2b9 100644 --- a/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -92,6 +92,13 @@ public function testFirewalls() 'security.authentication.listener.anonymous.host', 'security.access_listener', ), + array( + 'security.channel_listener', + 'security.context_listener.1', + 'security.authentication.listener.basic.with_user_checker', + 'security.authentication.listener.anonymous.with_user_checker', + 'security.access_listener', + ), ), $listeners); } @@ -231,6 +238,21 @@ public function testRememberMeThrowExceptions() $this->assertFalse($service->getArgument(5)); } + public function testUserCheckerConfig() + { + $this->assertEquals('app.user_checker', $this->getContainer('container1')->getAlias('security.user_checker.with_user_checker')); + } + + public function testUserCheckerConfigWithDefaultChecker() + { + $this->assertEquals('security.user_checker', $this->getContainer('container1')->getAlias('security.user_checker.host')); + } + + public function testUserCheckerConfigWithNoCheckers() + { + $this->assertEquals('security.user_checker', $this->getContainer('container1')->getAlias('security.user_checker.secure')); + } + protected function getContainer($file) { $container = new ContainerBuilder(); diff --git a/Tests/DependencyInjection/Fixtures/php/container1.php b/Tests/DependencyInjection/Fixtures/php/container1.php index 4521c8cd..4789a6d3 100644 --- a/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/Tests/DependencyInjection/Fixtures/php/container1.php @@ -72,6 +72,7 @@ 'remote_user' => true, 'logout' => true, 'remember_me' => array('secret' => 'TheSecret'), + 'user_checker' => null, ), 'host' => array( 'pattern' => '/test', @@ -80,6 +81,11 @@ 'anonymous' => true, 'http_basic' => true, ), + 'with_user_checker' => array( + 'user_checker' => 'app.user_checker', + 'anonymous' => true, + 'http_basic' => true, + ), ), 'access_control' => array( diff --git a/Tests/DependencyInjection/Fixtures/xml/container1.xml b/Tests/DependencyInjection/Fixtures/xml/container1.xml index e5f5905f..61873a9f 100644 --- a/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -55,6 +55,7 @@ + @@ -64,6 +65,12 @@ + + + + app.user_checker + + ROLE_USER ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH ROLE_USER,ROLE_ADMIN diff --git a/Tests/DependencyInjection/Fixtures/yml/container1.yml b/Tests/DependencyInjection/Fixtures/yml/container1.yml index 6b27806e..e14e7931 100644 --- a/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -56,6 +56,8 @@ security: logout: true remember_me: secret: TheSecret + user_checker: ~ + host: pattern: /test host: foo\.example\.org @@ -63,6 +65,11 @@ security: anonymous: true http_basic: true + with_user_checker: + anonymous: ~ + http_basic: ~ + user_checker: app.user_checker + role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] diff --git a/Tests/DependencyInjection/MainConfigurationTest.php b/Tests/DependencyInjection/MainConfigurationTest.php index 8d922467..9d8009ea 100644 --- a/Tests/DependencyInjection/MainConfigurationTest.php +++ b/Tests/DependencyInjection/MainConfigurationTest.php @@ -46,7 +46,7 @@ public function testNoConfigForProvider() $processor = new Processor(); $configuration = new MainConfiguration(array(), array()); - $config = $processor->processConfiguration($configuration, array($config)); + $processor->processConfiguration($configuration, array($config)); } /** @@ -65,7 +65,7 @@ public function testManyConfigForProvider() $processor = new Processor(); $configuration = new MainConfiguration(array(), array()); - $config = $processor->processConfiguration($configuration, array($config)); + $processor->processConfiguration($configuration, array($config)); } public function testCsrfAliases() @@ -108,8 +108,35 @@ public function testCsrfOriginalAndAliasValueCausesException() ); $config = array_merge(static::$minimalConfig, $config); + $processor = new Processor(); + $configuration = new MainConfiguration(array(), array()); + $processor->processConfiguration($configuration, array($config)); + } + + public function testDefaultUserCheckers() + { + $processor = new Processor(); + $configuration = new MainConfiguration(array(), array()); + $processedConfig = $processor->processConfiguration($configuration, array(static::$minimalConfig)); + + $this->assertEquals('security.user_checker', $processedConfig['firewalls']['stub']['user_checker']); + } + + public function testUserCheckers() + { + $config = array( + 'firewalls' => array( + 'stub' => array( + 'user_checker' => 'app.henk_checker', + ), + ), + ); + $config = array_merge(static::$minimalConfig, $config); + $processor = new Processor(); $configuration = new MainConfiguration(array(), array()); $processedConfig = $processor->processConfiguration($configuration, array($config)); + + $this->assertEquals('app.henk_checker', $processedConfig['firewalls']['stub']['user_checker']); } } diff --git a/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php b/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php index cfbc3785..4c163485 100644 --- a/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php +++ b/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php @@ -109,6 +109,7 @@ public function testBasicCreate() 'index_0' => array(new Reference('authenticator123')), 'index_1' => new Reference('my_user_provider'), 'index_2' => 'my_firewall', + 'index_3' => new Reference('security.user_checker.my_firewall'), ), $providerDefinition->getArguments()); $listenerDefinition = $container->getDefinition('security.authentication.listener.guard.my_firewall'); @@ -123,7 +124,7 @@ public function testExistingDefaultEntryPointUsed() 'authenticators' => array('authenticator123'), 'entry_point' => null, ); - list($container, $entryPointId) = $this->executeCreate($config, 'some_default_entry_point'); + list(, $entryPointId) = $this->executeCreate($config, 'some_default_entry_point'); $this->assertEquals('some_default_entry_point', $entryPointId); }