9

EXPLANATION

Allowing user to switch to any other user is easy in Symfony2. My question is, how to allow certain user to switch only to certain other users? I'm using FOSUserBundle as my users provider.

EXAMPLE

There is 5 users, UserA, UserB, UserC, UserD, UserE, but only 3 of them are linked together.

UserA can switch to UserB and UserC

UserB can switch to UserA and UserC

UserC can switch to UserA and UserB

Thanks for your help!

3 Answers 3

15

You could possibly implement this type of thing by overriding the default SwitchUserListener.

The parameter you would override is: security.authentication.switchuser_listener.class

For example, in parameters.yml:

parameters:
  security.authentication.switchuser_listener.class: My\Project\Security\Listener\SwitchUserListener

Where, in your custom listener class, you'd implement Symfony\Component\Security\Http\Firewall\ListenerInterface and use the existing Symfony\Component\Security\Http\Firewall\SwitchUserListener class as a basis for your custom implementation.

0
2

If you want to impersonate Admin Users in to Regular user there are some examples :)

https://gist.github.com/1589120

http://symfony.com/doc/current/book/security.html#impersonating-a-user

4
  • As I understand, once user has ROLE_ALLOWED_TO_SWITCH, he/she can append ?_switch_user=anyusernamethatexists to the url and is able to switch to that user. How to allow user to switch only to certain other users? Nov 14, 2012 at 10:46
  • I suppose that is there some switch user listener. I will check in the symfony source. Nov 15, 2012 at 11:45
  • Have you checked the source yet? Thanks for help! Nov 20, 2012 at 1:42
  • The Symfony documentation link has changed: symfony.com/doc/current/cookbook/security/…
    – ausi
    Jul 30, 2014 at 12:05
0

Thanks to Veonik, a (maybe dirty) way to do that

Add a role with that syntax :

 ROLE_ALLOWED_TO_SWITCH_{usertype}

For example add ROLE_A to userA :

ROLE_A:
 - ROLE_ALLOWED_TO_SWITCH_USERTYPEB
 - ROLE_ALLOWED_TO_SWITCH_USERTYPEC

Declare your own SwitchUserListener service in yml :

security.authentication.switchuser_listener:
  class: %security.authentication.switchuser_listener.class%
  public: false
  abstract: true
  tags:
      - { name: monolog.logger, channel: security}
  arguments: 
   - @security.context
   - null
   - @security.user_checker
   - null
   - @security.access.decision_manager
   - @logger
   - _switch_user
   - ROLE_ALLOWED_TO_SWITCH 
   - @event_dispatcher
   - @security.role_hierarchy

In SwitchUserListener::attemptSwitchUser method

private function attemptSwitchUser(Request $request)
{
 ....
 CODE BEFORE
 ....
    $user = $this->provider->loadUserByUsername($username);
    $rtoSwith = $this->getRolesToSwitchTo($token->getRoles());
    $accessGranted = false;
    foreach ($rtoSwith as $suType) {
        $instance = ucfirst(strtolower($suType));
        if ($user instanceof $instance) {
            $accessGranted = true;
            break;
        }
    }

    if (!$accessGranted) {

        throw new AccessDeniedException('Access Denied, not allowed to switch to type : '.get_class($user));
    }
 ....
 CODE AFTER 
 ....
 return $token
}

protected function getRolesToSwitchTo($roles){

    $rts = array();
    foreach ($this->roleHierarchy->getReachableRoles($roles) as $role) {

        $tmp = explode("ROLE_ALLOWED_TO_SWITCH_", $role->getRole());

        if(isset($tmp[1])){
            $rts[] = $tmp[1];
        }
    }

    return $rts;
}

Tell me if you have another solution ++

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.