Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does symfony listen for the _switch_user?

Tags:

symfony

I have an application in which I have a superadmin role and various user roles with different privileges. I want to be able to impersonate as any of these users using the _switch_user query as shown on http://symfony.com/doc/current/book/security.html#impersonating-a-user

However, when I add the query to the end of my url, it doesn't seem to do anything. I've played around with this for a long time now and can't seem to find a solution. I know that the user I'm logged in as has ROLE_ALLOWED_TO_SWITCH, but I can't quite seem to figure out how symfony does it.

I'm using a custom authentication provider so I think it has something to do with that, but I'm not sure what I need to be looking at. I can post any code needed, but I'm really not sure what to post right now.

like image 557
Squazic Avatar asked Aug 28 '12 21:08

Squazic


1 Answers

So I dug around some more and found out that the Listener class for my custom authentication provider was not written properly. It was written such that a new Token was created on every page load.

Two things needed to be done as a result.

The first was to change the authentication listener to be similar to those in the Symfony Firewall Listeners, the general structure of which is shown below.

if (null !== $token = $this->securityContext->getToken()) {
    if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() &&
        $token->getUsername() === $username) {
            return;
    }
}

These listeners basically allow the authentication to proceed without creating a new token if certain conditions hold. These conditions being that the token is an instance of the right token, it's authenticated, and the username matches that of the logged in user.

Secondly, this code had to be modified to check authentication based on the original user if he tried to switch users. This issue details a similar problem someone else had. The fix was to cycle through the roles to find a SwitchUserRole and use that data to authenticate. I've copied the patch below, which would go after the initial if statement above.

foreach ($token->getRoles() as $role) {
    if ($role instanceof SwitchUserRole) {
        $token = $role->getSource();
            break;
    }
}

Together, the authentication listener will only create a new token if it doesn't pass certain conditions and a user who is impersonating another will have their credentials used for testing authentication instead of that of the user they're trying to impersonate.

like image 117
Squazic Avatar answered Nov 15 '22 09:11

Squazic