Skip to content

Commit e0a86d1

Browse files
committed
Merge branch '4.2' into 4.3
* 4.2: Fixing docs about switch_user and custom voters
2 parents 06ef5a3 + 02904b3 commit e0a86d1

File tree

1 file changed

+79
-21
lines changed

1 file changed

+79
-21
lines changed

security/impersonating_user.rst

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -195,25 +195,81 @@ also adjust the query parameter name via the ``parameter`` setting:
195195
Limiting User Switching
196196
-----------------------
197197

198-
If you need more control over user switching, but don't require the complexity
199-
of a full ACL implementation, you can use a security voter. For example, you
200-
may want to allow employees to be able to impersonate a user with the
201-
``ROLE_CUSTOMER`` role without giving them the ability to impersonate a more
202-
elevated user such as an administrator.
198+
If you need more control over user switching, you can use a security voter. First,
199+
configure ``switch_user`` to check for some new, custom attribute. This can be
200+
anything, but *cannot* start with ``ROLE_`` (to enforce that only your voter will)
201+
be called:
203202

204-
Create the voter class::
203+
.. configuration-block::
204+
205+
.. code-block:: yaml
206+
207+
# config/packages/security.yaml
208+
security:
209+
# ...
210+
211+
firewalls:
212+
main:
213+
# ...
214+
switch_user: { role: CAN_SWITCH_USER }
215+
216+
.. code-block:: xml
217+
218+
<!-- config/packages/security.xml -->
219+
<?xml version="1.0" encoding="UTF-8"?>
220+
<srv:container xmlns="http://symfony.com/schema/dic/security"
221+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
222+
xmlns:srv="http://symfony.com/schema/dic/services"
223+
xsi:schemaLocation="http://symfony.com/schema/dic/services
224+
https://symfony.com/schema/dic/services/services-1.0.xsd">
225+
<config>
226+
<!-- ... -->
227+
228+
<firewall name="main">
229+
<!-- ... -->
230+
<switch-user role="CAN_SWITCH_USER" />
231+
</firewall>
232+
</config>
233+
</srv:container>
234+
235+
.. code-block:: php
236+
237+
// config/packages/security.php
238+
$container->loadFromExtension('security', [
239+
// ...
240+
241+
'firewalls' => [
242+
'main'=> [
243+
// ...
244+
'switch_user' => [
245+
'role' => 'CAN_SWITCH_USER',
246+
],
247+
],
248+
],
249+
]);
250+
251+
Then, create a voter class that responds to this role and includes whatever custom
252+
logic you want::
205253

206254
namespace App\Security\Voter;
207255

208256
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
209257
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
258+
use Symfony\Component\Security\Core\Security;
210259
use Symfony\Component\Security\Core\User\UserInterface;
211260

212261
class SwitchToCustomerVoter extends Voter
213262
{
263+
private $security;
264+
265+
public function __construct(Security $security)
266+
{
267+
$this->security = $security;
268+
}
269+
214270
protected function supports($attribute, $subject)
215271
{
216-
return in_array($attribute, ['ROLE_ALLOWED_TO_SWITCH'])
272+
return in_array($attribute, ['CAN_SWITCH_USER'])
217273
&& $subject instanceof UserInterface;
218274
}
219275

@@ -225,27 +281,29 @@ Create the voter class::
225281
return false;
226282
}
227283

228-
if (in_array('ROLE_CUSTOMER', $subject->getRoles())
229-
&& in_array('ROLE_SWITCH_TO_CUSTOMER', $token->getRoleNames(), true)) {
284+
// you can still check for ROLE_ALLOWED_TO_SWITCH
285+
if ($this->security->isGranted('ROLE_ALLOWED_TO_SWITCH')) {
286+
return true;
287+
}
288+
289+
// check for any roles you want
290+
if ($this->security->isGranted('ROLE_TECH_SUPPORT')) {
230291
return true;
231292
}
232293

294+
/*
295+
* or use some custom data from your User object
296+
if ($user->isAllowedToSwitch()) {
297+
return true;
298+
}
299+
*/
300+
233301
return false;
234302
}
235303
}
236304

237-
.. versionadded:: 4.3
238-
239-
The ``getRoleNames()`` method was introduced in Symfony 4.3.
240-
241-
To enable the new voter in the app, register it as a service and
242-
:doc:`tag it </service_container/tags>` with the ``security.voter``
243-
tag. If you're using the
244-
:ref:`default services.yaml configuration <service-container-services-load-example>`,
245-
this is already done for you, thanks to :ref:`autoconfiguration <services-autoconfigure>`.
246-
247-
Now a user who has the ``ROLE_SWITCH_TO_CUSTOMER`` role can switch to a user who
248-
has the ``ROLE_CUSTOMER`` role, but not other users.
305+
That's it! When switching users, your voter now has full control over whether or
306+
not this is allowed. If your voter isn't called, see :ref:`declaring-the-voter-as-a-service`.
249307

250308
Events
251309
------

0 commit comments

Comments
 (0)