Description
Symfony provides native support for multiple user providers. This makes it easy to integrate any kind of login handlers, including SSO and existing 3rd party bundles (e.g. FR3DLdapBundle, HWIOauthBundle, FOSUserBundle, BeSimpleSsoAuthBundle, etc.).
However, to be able to use external user providers with eZ, a valid eZ user needs to be injected into the repository. This is mainly for the kernel to be able to manage content-related permissions (but not limited to this).
Depending on your context, you will either want to create an eZ user on-the-fly
, return an existing user, or even always use a generic user.
Solution
Whenever an external user is matched (i.e. one that does not come from eZ repository, like coming from LDAP), eZ kernel fires an MVCEvents::INTERACTIVE_LOGIN
event. Every service listening to this event will receive an eZ\Publish\Core\MVC\Symfony\Event\InteractiveLoginEvent
object which contains the original security token (that holds the matched user) and the request.
It's then up to the listener to retrieve an eZ user from the repository and to assign it back to the event object. This user will be injected into the repository and used for the rest of the request.
User exposed and security token
When an external user is matched, a different token will be injected into the security context, the InteractiveLoginToken
. This token holds a UserWrapped
instance which contains the originally matched user and the API user (the one from the eZ repository).
Note that the API user is mainly used for permission checks against the repository and thus stays under the hood.
Customizing the user class
It is possible to customize the user class used by extending ezpublish.security.login_listener
service, which defaults to eZ\Publish\Core\MVC\Symfony\Security\EventListener\SecurityListener
.
You can override getUser()
to return whatever user class you want, as long as it implements eZ\Publish\Core\MVC\Symfony\Security\UserInterface
.
Example
Here is a very simple example using the in-memory user provider.
Implementing the listener