I have a Symfony application with two firewalls, one for admins and one for normal users.
admin:
provider: admin
# etc
main_site:
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
I'd like admin users to be able to impersonate normal users. How can I do this, given that they're using separate firewalls and separate user providers?
There were several things I had to do to get this to work.
Context key: As described here, I had to give both firewalls the same context. Without this, admins were taken to the login page when trying to switch users.
Config on both firewalls: I had to add the basic switch_user
configuration keys to both firewalls:
switch_user:
role: ROLE_ADMIN
If I just put the config on the main_site
firewall, admins got an access denied message when exiting impersonation and going to an admin page. (For example, the route /admin/dashboard?_switch_user=_exit
would give a 403).
Provider key on the main_site
's config:
main_site:
switch_user:
role: ROLE_ADMIN
provider: fos_userbundle
Without this, I got the error "Switch User failed - user@example.com not found". Digging into the code, it turned out that the admin
user provider was being used, and of course the normal users couldn't be found when using that provider.
(provider
key for switch_user
config discussed here.)
Alternatively, I could have added this as a provider key for the firewall itself:
main_site:
switch_user:
role: ROLE_ADMIN
provider: fos_userbundle
You'll see from the config in my question that fos_userbundle
was only specified as a provider for form_login
, not for main_site
as a whole, which is why it wasn't being used until I added it. Adding it in either place (impersonation config or whole firewall) would do the trick.
Here's the full set of relevant config:
admin:
provider: admin
# Have to put basic switch_user config on both firewalls
switch_user:
role: ROLE_ADMIN
# Both the admin and main_site firewalls have the same context, to allow
# cross-firewall impersonation
# https://stackoverflow.com/a/17991481/328817
context: boardworks
main_site:
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
switch_user:
role: ROLE_ADMIN
# Have to explicitly set the provider, otherwise the site will use the admin
# user provider when looking up the users whom admins are trying to impersonate
provider: fos_userbundle
# Rather than adding the provider above, I could have added it here:
#provider: fos_userbundle