diff --git a/security/user_checkers.rst b/security/user_checkers.rst index 32349020a50..3c13a57e239 100644 --- a/security/user_checkers.rst +++ b/security/user_checkers.rst @@ -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.`` tag (where ```` 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 + + + + + + + + + + + + + + + + + + + + .. 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.`` 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 + + + + + + + + + + + + + + + + + .. 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') + // ... + ; + };