@@ -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+
190256Events
191257------
192258