Skip to content

Commit 3728e82

Browse files
committed
minor #10842 Add example for using a voter to restrict switch_user (jwmickey, javiereguiluz)
This PR was merged into the 4.1 branch. Discussion ---------- Add example for using a voter to restrict switch_user This recreates #9353, which has too many conflicts when merging it. Commits ------- 7853ec0 Minor tweaks 876257b implemented community suggestions e6c569b Fix recommendations from community review cf3bd00 [WIP] add example for using a voter to restrict switch_user
2 parents 7d2199f + 7853ec0 commit 3728e82

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

security/impersonating_user.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,72 @@ also adjust the query parameter name via the ``parameter`` setting:
187187
),
188188
));
189189
190+
Limiting User Switching
191+
-----------------------
192+
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.
198+
199+
.. versionadded:: 4.1
200+
201+
The target user was added as the voter subject parameter in Symfony 4.1.
202+
203+
Create the voter class::
204+
205+
namespace App\Security\Voter;
206+
207+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
208+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
209+
use Symfony\Component\Security\Core\User\UserInterface;
210+
211+
class SwitchToCustomerVoter extends Voter
212+
{
213+
protected function supports($attribute, $subject)
214+
{
215+
return in_array($attribute, ['ROLE_ALLOWED_TO_SWITCH'])
216+
&& $subject instanceof UserInterface;
217+
}
218+
219+
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
220+
{
221+
$user = $token->getUser();
222+
// if the user is anonymous or if the subject is not a user, do not grant access
223+
if (!$user instanceof UserInterface || !$subject instanceof UserInterface) {
224+
return false;
225+
}
226+
227+
if (in_array('ROLE_CUSTOMER', $subject->getRoles())
228+
&& $this->hasSwitchToCustomerRole($token)) {
229+
return true;
230+
}
231+
232+
return false;
233+
}
234+
235+
private function hasSwitchToCustomerRole(TokenInterface $token)
236+
{
237+
foreach ($token->getRoles() as $role) {
238+
if ($role->getRole() === 'ROLE_SWITCH_TO_CUSTOMER') {
239+
return true;
240+
}
241+
}
242+
243+
return false;
244+
}
245+
}
246+
247+
To enable the new voter in the app, register it as a service and
248+
:doc:`tag it </service_container/tags>` with the ``security.voter``
249+
tag. If you're using the
250+
:ref:`default services.yaml configuration <service-container-services-load-example>`,
251+
this is already done for you, thanks to :ref:`autoconfiguration <services-autoconfigure>`.
252+
253+
Now a user who has the ``ROLE_SWITCH_TO_CUSTOMER`` role can switch to a user who
254+
has the ``ROLE_CUSTOMER`` role, but not other users.
255+
190256
Events
191257
------
192258

0 commit comments

Comments
 (0)