feature #24114 [SecurityBundle] Throw a meaningful exception when an undefined user provider is used inside a firewall (chalasr)

This PR was merged into the 3.4 branch.

Discussion
----------

[SecurityBundle] Throw a meaningful exception when an undefined user provider is used inside a firewall

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Before

> The service "security.authentication.manager" has a dependency on a non-existent service "security.user.provider.concrete.undefined_provider".

After

> Invalid firewall "main": user provider "undefined_provider" not found.

Commits
-------

b884c6612d Throw a meaningful exception when an undefined user provider is used inside a firewall
This commit is contained in:
Fabien Potencier 2017-09-07 07:47:43 -07:00
commit 22c00283bb
8 changed files with 124 additions and 3 deletions

View File

@ -332,6 +332,9 @@ class SecurityExtension extends Extension
// Provider id (take the first registered provider if none defined)
if (isset($firewall['provider'])) {
$defaultProvider = $this->getUserProviderId($firewall['provider']);
if (!in_array($defaultProvider, $providerIds, true)) {
throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall['provider']));
}
} else {
$defaultProvider = reset($providerIds);
}
@ -422,7 +425,7 @@ class SecurityExtension extends Extension
$configuredEntryPoint = isset($firewall['entry_point']) ? $firewall['entry_point'] : null;
// Authentication listeners
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $configuredEntryPoint);
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint);
$config->replaceArgument(7, $configuredEntryPoint ?: $defaultEntryPoint);
@ -477,7 +480,7 @@ class SecurityExtension extends Extension
return $this->contextListeners[$contextKey] = $listenerId;
}
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, $defaultEntryPoint)
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, array $providerIds, $defaultEntryPoint)
{
$listeners = array();
$hasListeners = false;
@ -487,7 +490,14 @@ class SecurityExtension extends Extension
$key = str_replace('-', '_', $factory->getKey());
if (isset($firewall[$key])) {
$userProvider = isset($firewall[$key]['provider']) ? $this->getUserProviderId($firewall[$key]['provider']) : $defaultProvider;
if (isset($firewall[$key]['provider'])) {
if (!in_array($firewall[$key]['provider'], $providerIds, true)) {
throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall[$key]['provider']));
}
$userProvider = $this->getUserProviderId($firewall[$key]['provider']);
} else {
$userProvider = $defaultProvider;
}
list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint);

View File

@ -387,6 +387,24 @@ abstract class CompleteConfigurationTest extends TestCase
$container = $this->getContainer('access_decision_manager_service_and_strategy');
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Invalid firewall "main": user provider "undefined" not found.
*/
public function testFirewallUndefinedUserProvider()
{
$this->getContainer('firewall_undefined_provider');
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Invalid firewall "main": user provider "undefined" not found.
*/
public function testFirewallListenerUndefinedProvider()
{
$this->getContainer('listener_undefined_provider');
}
protected function getContainer($file)
{
$file = $file.'.'.$this->getFileExtension();

View File

@ -0,0 +1,17 @@
<?php
$container->loadFromExtension('security', array(
'providers' => array(
'default' => array(
'memory' => array(
'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')),
),
),
),
'firewalls' => array(
'main' => array(
'provider' => 'undefined',
'form_login' => true,
),
),
));

View File

@ -0,0 +1,16 @@
<?php
$container->loadFromExtension('security', array(
'providers' => array(
'default' => array(
'memory' => array(
'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')),
),
),
),
'firewalls' => array(
'main' => array(
'form_login' => array('provider' => 'undefined'),
),
),
));

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://symfony.com/schema/dic/security"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<sec:config>
<sec:providers>
<sec:provider name="default" id="foo" />
</sec:providers>
<sec:firewalls>
<sec:firewall name="main" provider="undefined">
<sec:form_login />
</sec:firewall>
</sec:firewalls>
</sec:config>
</container>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://symfony.com/schema/dic/security"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<sec:config>
<sec:providers>
<sec:provider name="default" id="foo" />
</sec:providers>
<sec:firewalls>
<sec:firewall name="main">
<sec:form_login provider="undefined" />
</sec:firewall>
</sec:firewalls>
</sec:config>
</container>

View File

@ -0,0 +1,10 @@
security:
providers:
default:
memory:
users: { foo: { password: foo, roles: ROLE_USER } }
firewalls:
main:
provider: undefined
form_login: true

View File

@ -0,0 +1,10 @@
security:
providers:
default:
memory:
users: { foo: { password: foo, roles: ROLE_USER } }
firewalls:
main:
form_login:
provider: undefined