@@ -190,25 +190,81 @@ also adjust the query parameter name via the ``parameter`` setting:
190190 Limiting User Switching
191191-----------------------
192192
193- If you need more control over user switching, but don't require the complexity
194- of a full ACL implementation, you can use a security voter. For example, you
195- may want to allow employees to be able to impersonate a user with the
196- ``ROLE_CUSTOMER `` role without giving them the ability to impersonate a more
197- elevated user such as an administrator.
193+ If you need more control over user switching, you can use a security voter. First,
194+ configure ``switch_user `` to check for some new, custom attribute. This can be
195+ anything, but *cannot * start with ``ROLE_ `` (to enforce that only your voter will)
196+ be called:
198197
199- Create the voter class::
198+ .. configuration-block ::
199+
200+ .. code-block :: yaml
201+
202+ # config/packages/security.yaml
203+ security :
204+ # ...
205+
206+ firewalls :
207+ main :
208+ # ...
209+ switch_user : { role: CAN_SWITCH_USER }
210+
211+ .. code-block :: xml
212+
213+ <!-- config/packages/security.xml -->
214+ <?xml version =" 1.0" encoding =" UTF-8" ?>
215+ <srv : container xmlns =" http://symfony.com/schema/dic/security"
216+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
217+ xmlns : srv =" http://symfony.com/schema/dic/services"
218+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
219+ https://symfony.com/schema/dic/services/services-1.0.xsd" >
220+ <config >
221+ <!-- ... -->
222+
223+ <firewall name =" main" >
224+ <!-- ... -->
225+ <switch-user role =" CAN_SWITCH_USER" />
226+ </firewall >
227+ </config >
228+ </srv : container >
229+
230+ .. code-block :: php
231+
232+ // config/packages/security.php
233+ $container->loadFromExtension('security', [
234+ // ...
235+
236+ 'firewalls' => [
237+ 'main'=> [
238+ // ...
239+ 'switch_user' => [
240+ 'role' => 'CAN_SWITCH_USER',
241+ ],
242+ ],
243+ ],
244+ ]);
245+
246+ Then, create a voter class that responds to this role and includes whatever custom
247+ logic you want::
200248
201249 namespace App\Security\Voter;
202250
203251 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
204252 use Symfony\Component\Security\Core\Authorization\Voter\Voter;
253+ use Symfony\Component\Security\Core\Security;
205254 use Symfony\Component\Security\Core\User\UserInterface;
206255
207256 class SwitchToCustomerVoter extends Voter
208257 {
258+ private $security;
259+
260+ public function __construct(Security $security)
261+ {
262+ $this->security = $security;
263+ }
264+
209265 protected function supports($attribute, $subject)
210266 {
211- return in_array($attribute, ['ROLE_ALLOWED_TO_SWITCH '])
267+ return in_array($attribute, ['CAN_SWITCH_USER '])
212268 && $subject instanceof UserInterface;
213269 }
214270
@@ -220,34 +276,29 @@ Create the voter class::
220276 return false;
221277 }
222278
223- if (in_array('ROLE_CUSTOMER', $subject->getRoles())
224- && $this->hasSwitchToCustomerRole($token )) {
279+ // you can still check for ROLE_ALLOWED_TO_SWITCH
280+ if ( $this->security->isGranted('ROLE_ALLOWED_TO_SWITCH' )) {
225281 return true;
226282 }
227283
228- return false;
229- }
284+ // check for any roles you want
285+ if ($this->security->isGranted('ROLE_TECH_SUPPORT')) {
286+ return true;
287+ }
230288
231- private function hasSwitchToCustomerRole(TokenInterface $token)
232- {
233- foreach ($token->getRoles() as $role) {
234- if ($role->getRole() === 'ROLE_SWITCH_TO_CUSTOMER') {
235- return true;
236- }
289+ /*
290+ * or use some custom data from your User object
291+ if ($user->isAllowedToSwitch()) {
292+ return true;
237293 }
294+ */
238295
239296 return false;
240297 }
241298 }
242299
243- To enable the new voter in the app, register it as a service and
244- :doc: `tag it </service_container/tags >` with the ``security.voter ``
245- tag. If you're using the
246- :ref: `default services.yaml configuration <service-container-services-load-example >`,
247- this is already done for you, thanks to :ref: `autoconfiguration <services-autoconfigure >`.
248-
249- Now a user who has the ``ROLE_SWITCH_TO_CUSTOMER `` role can switch to a user who
250- has the ``ROLE_CUSTOMER `` role, but not other users.
300+ That's it! When switching users, your voter now has full control over whether or
301+ not this is allowed. If your voter isn't called, see :ref: `declaring-the-voter-as-a-service `.
251302
252303Events
253304------
0 commit comments