Message-ID: <1829184527.2762.1485850726189.JavaMail.confluence@ip-10-127-227-164> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_2761_1173323808.1485850726189" ------=_Part_2761_1173323808.1485850726189 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html Authenticating a user with multiple user providers

Authenticating a user with multiple user providers

=20
=20
=20
=20

Descrip= tion

Symfony provides native support for multiple user providers. This makes it easy to i= ntegrate any kind of login handlers, including SSO and existing 3rd party b= undles (e.g. FR3DLdapBundleHWIOauthBundleFOSUserBundle,&= nbsp;BeSimpleSsoAuthBundle, etc.).

However, to be able to use external user providers wi= th eZ, a valid eZ user needs to be injected into the repository. This is ma= inly for the kernel to be able to manage content-related permissions (but n= ot limited to this).

Depending on your context, you will either want to create an eZ user&nbs= p;on-the-fly, return an existing user, or even always use a ge= neric user.

Solution

Whenever an external user is matched (i.e. one that does n= ot come from eZ repository, like coming from LDAP), eZ kernel fires an = ;MVCEvents::INTERACTIVE_LOGIN event. Every service listen= ing to this event will receive an eZ\Publish\Core\MVC\Symfony\Event\I= nteractiveLoginEvent object which contains the original securit= y 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.

If no eZ user is returned, the anonymous user will be used.

User exposed and security token

When an external user is matched, a different token will b= e injected into the security context, the InteractiveLoginToken<= /code>. This token holds a UserWrapped instance whic= h 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.<= /p>

Customizing the user class

It is possible to customize the user class used by extending = ezpublish.security.login_listener service, which defaults to&nb= sp;eZ\Publish\Core\MVC\Symfony\Security\EventListener\SecurityListene= r.

You can override getUser() to return whatever use= r class you want, as long as it implements eZ\Publish\Core\MVC\S= ymfony\Security\UserInterface.

Example

Here is a very simple example using the in-memory user provider.

app/config/security.yml
=20
security:
    providers:
        # Chaining in_memory and ezpublish user providers
        chain_provider:
            chain:
                providers: [in_memory, ezpublish]
        ezpublish:
            id: ezpublish.security.user_provider
        in_memory:
            memory:
                users:
                    # You will then be able to login with username "user" a=
nd password "userpass"
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
=09# The "in memory" provider requires an encoder for Symfony\Component\Sec=
urity\Core\User\User
 encoders:
        Symfony\Component\Security\Core\User\User: plaintext
=20

Implementing the listener

services.yml in your AcmeTestBundle
=20
parameters:
    acme_test.interactive_event_listener.class: Acme\TestBundle\EventListen=
er\InteractiveLoginListener

services:
    acme_test.interactive_event_listener:
        class: %acme_test.interactive_event_listener.class%
        arguments: [@ezpublish.api.service.user]
        tags:
            - { name: kernel.event_subscriber } 
=20

Do not mix MVCEvents::INTERACTIVE_LOGIN event (specific to = eZ Platform) and SecurityEvents::INTERACTIVE_LOGIN event (fire= d by Symfony security component)

Interactive login listener
=20
<?php
namespace Acme\TestBundle\EventListener;

use eZ\Publish\API\Repository\UserService;
use eZ\Publish\Core\MVC\Symfony\Event\InteractiveLoginEvent;
use eZ\Publish\Core\MVC\Symfony\MVCEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class InteractiveLoginListener implements EventSubscriberInterface
{
    /**
     * @var \eZ\Publish\API\Repository\UserService
     */
    private $userService;

    public function __construct( UserService $userService )
    {
        $this->userService =3D $userService;
    }

    public static function getSubscribedEvents()
    {
        return array(
            MVCEvents::INTERACTIVE_LOGIN =3D> 'onInteractiveLogin'
        );
    }

    public function onInteractiveLogin( InteractiveLoginEvent $event )
    {
        // We just load a generic user and assign it back to the event.
        // You may want to create users here, or even load predefined users=
 depending on your own rules.
        $event->setApiUser( $this->userService->loadUserByLogin( '=
lolautruche' ) );
    }
} 
=20


=20
=20
=20
=20

In thi= s topic:

=20
=20
=20
------=_Part_2761_1173323808.1485850726189--