Description
I'm implementing an application that needs to have separate sets of users for its different sections. For instance, we create Admin and Front sections. For each of the sections I define a firewall rule in security config and a different user provider:
providers:
provider_admin:
id: acme.shmundle.my_user_provider.admin
provider_front:
id: acme.shmundle.my_user_provider.front
firewalls:
admin:
provider: provider_admin
....
front:
provider: provider_front
....
Now, the provider ids reference two different services of the same class that implements UserProviderInterface configured to use different user storages, but same user class.
This setup leads to a problem in ContextListener. After user logs in, the ContextListener attempts to validate user token and refresh user by iterating over every user provider and calling its refreshUser method. If current user provider does not support the user class it throws UnsupportedUserException and ContextListener continues to the next user provider, but if it does and can't actually find the user it throws UsernameNotFoundException which interrupts the iteration and returns null essentially forcing the user to log out.
One solution that would work here is to make sure a different user class used for every user provider, so the iteration always reaches the provider that can refresh user token. But this solution seems quirky, non-obvious and moreover is a kind of side effect depending on the internal implementation of ContextListener.
Another solution is obviously to implement my own ContextListener that will iterate through every user provider regardless of the exceptions thrown. This is the approach I think I will have to take if you confirm that this behavior is actually intended and my use case doesn't lie within symfony's design philosophy.
Please refer to the ContextListener source for the problematic code.