@@ -187,6 +187,72 @@ also adjust the query parameter name via the ``parameter`` setting:
187
187
),
188
188
));
189
189
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
+
190
256
Events
191
257
------
192
258
0 commit comments