Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions security/user_checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,148 @@ is the service id of your user checker:
// ...
;
};

Using Multiple User Checkers
----------------------------

.. versionadded:: 6.2

The ``ChainUserChecker`` class was added in Symfony 6.2.

It is common for applications to have multiple authentication entry points (such as
traditional form based login and an API) which may have unique checker rules for each
entry point as well as common rules for all entry points. To allow using multiple user
checkers on a firewall, a service for the :class:`Symfony\\Component\\Security\\Core\\User\\ChainUserChecker`
class is created for each firewall.

To use the chain user checker, first you will need to tag your user checker services with the
``security.user_checker.<firewall>`` tag (where ``<firewall>`` is the name of the firewall
in your security configuration). The service tag also supports the priority attribute, allowing you to define the
order in which user checkers are called::

.. configuration-block::

.. code-block:: yaml

# config/services.yaml

# ...
services:
App\Security\AccountEnabledUserChecker:
tags:
- { name: security.user_checker.api, priority: 10 }
- { name: security.user_checker.main, priority: 10 }

App\Security\APIAccessAllowedUserChecker:
tags:
- { name: security.user_checker.api, priority: 5 }

.. code-block:: xml

<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<!-- ... -->

<service id="App\Security\AccountEnabledUserChecker">
<tag name="security.user_checker.api" priority="10"/>
<tag name="security.user_checker.main" priority="10"/>
</service>

<service id="App\Security\APIAccessAllowedUserChecker">
<tag name="security.user_checker.api" priority="5"/>
</service>
</services>
</container>

.. code-block:: php

// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use App\Security\AccountEnabledUserChecker;
use App\Security\APIAccessAllowedUserChecker;

return function(ContainerConfigurator $configurator) {
$services = $configurator->services();

$services->set(AccountEnabledUserChecker::class)
->tag('security.user_checker.api', ['priority' => 10])
->tag('security.user_checker.main', ['priority' => 10]);

$services->set(APIAccessAllowedUserChecker::class)
->tag('security.user_checker.api', ['priority' => 5]);
};

Once your checker services are tagged, next you will need configure your firewalls to use the
``security.user_checker.chain.<firewall>`` service::

.. configuration-block::

.. code-block:: yaml

# config/packages/security.yaml

# ...
security:
firewalls:
api:
pattern: ^/api
user_checker: security.user_checker.chain.api
# ...
main:
pattern: ^/
user_checker: security.user_checker.chain.main
# ...

.. code-block:: xml

<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/security
https://symfony.com/schema/dic/security/security-1.0.xsd">

<config>
<!-- ... -->
<firewall name="api"
pattern="^/api"
user-checker="security.user_checker.chain.api">
<!-- ... -->
</firewall>
<firewall name="main"
pattern="^/"
user-checker="security.user_checker.chain.main">
<!-- ... -->
</firewall>
</config>
</srv:container>

.. code-block:: php

// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
// ...
$security->firewall('api')
->pattern('^/api')
->userChecker('security.user_checker.chain.api')
// ...
;

$security->firewall('main')
->pattern('^/')
->userChecker('security.user_checker.chain.main')
// ...
;
};