I would strongly advice you against doing such things on production platforms. You will be better off properly configuring User Impersonation instead. It will save you the headache of having to manually do all of this.
If you really, really, want to go this way you could try the code below:
/**
* @Route("/role/assign/{username}/{role}", name="role_assignment")
*
* @param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage
*
* @return JsonResponse
*/
public function assign($username, $role, TokenStorageInterface $tokenStorage)
{
// NOTES:
// 1. Make sure you are using the same User class as the one configured in `security.yml`
// 2. Keep in mind the $username MUST exist and MUST have the role you are setting,
// because the UserPasswordToken is reloaded from the session upon page refresh which triggers a check in the user provider and that will hit the database. In other words, if the user doesn't have `ROLE_ADMIN` you will most-likely get logged out or see "AccessDeniedException".
// For more information check \Symfony\Component\Security\Core\User\UserProviderInterface::refreshUser.
$user = new \Symfony\Component\Security\Core\User\User($username, null, array($role), true);
// Create token
$firewall = 'main'; // This MUST MATCH the name in your security.firewalls.->main<- or authentication WILL FAIL!
$usernamePasswordToken = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());
// You don't need to save the token via $session->save().
// You can directly use $tokenStorage, which will do that for you.
$tokenStorage->setToken($usernamePasswordToken);
// Pass authentication to client.
return new JsonResponse(['success' => 'true', 'user' => $user]);
}
If you are trying to authenticate for test cases, you can have a look at my answer here which shows how you can configure a client
which can authenticate as any user with any role you set (the user doesn't even have to exist in the db). This works fine for me on 3.4 so it should still work for 4.0.