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

How to authenticate a user with multiple user providers

Version compatibility

This recipe is compatible with eZ Publish 5.3 / 2014.01

 

=3D5.3/= 2014.01">EZP &= gt;=3D 5.3 / 2014.01

Desc= ription

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...).

However, to be able to use external user providers wi= th eZ, a valid eZ user needs to be injected in the repository. This is main= ly for the kernel to be able to manage content related permissions (but not= limited to).

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.

 

Solutio= n

Whenever a external user is matched (i.e. 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 a eZ\Publish\Core\MVC\Symfony\Eve= nt\InteractiveLoginEvent object which contains the original sec= urity token (that holds the matched user) and the request.

It's then up to the listener to retrieve an eZ user from repository and = assign it back to the event object. This user will be injected in the repos= itory and used for the rest of the request.

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

User exposed and security token

When a external user is matched, a different token wi= ll be injected in the security context, the InteractiveLoginToke= n. This token holds a UserWrapped instance wh= ich contains the originally matched user and the API user&nbs= p;(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<= /h2>

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

ezpublish/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 Publish) and SecurityEvents::INTERACTIVE_LOGIN event (fired= 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


 

 

 

+ # The "in memory" provider requires an encoder fo= r Symfony\Component\Security\Core\User\User

 

 

 
+ encoders:

 

 

 

+ Symfony\Component\Security\Core\User\User:

------=_Part_3531_380182123.1485853514805--