Version:

External Authentication Services

The portal engine provides several events to make it possible to integrate external authentication services via the login form.

  • Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginCheckPasswordEvent
  • Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginFieldTypeEvent
  • Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginGetUsserEvent
  • Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginPasswordChangeableEvent

Important: It is needed to create a PortalUser data object for all external users too to make the portal engine work correctly.

Example

This example event subscriber will allow Pimcore admin users to login to the portal engine as admin users too.

<?php

namespace AppBundle\EventListener;

use Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginCheckPasswordEvent;
use Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginFieldTypeEvent;
use Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginGetUserEvent;
use Pimcore\Bundle\PortalEngineBundle\Event\Auth\LoginPasswordChangeableEvent;
use Pimcore\Model\DataObject\PortalUser;
use Pimcore\Model\DataObject\Service;
use Pimcore\Model\User;
use Pimcore\Tool\Authentication;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PortalEngineAuthenticationSubscriber implements EventSubscriberInterface
{
    const USER_FOLDER = '/Portal Engine/Users/Pimcore';

    public static function getSubscribedEvents()
    {
        return [
            LoginFieldTypeEvent::class => 'onLoginFieldType',
            LoginGetUserEvent::class => 'onLoginGetUser',
            LoginCheckPasswordEvent::class => 'onLoginCheckPassword',
            LoginPasswordChangeableEvent::class => 'onPasswordChangeable',
        ];
    }

    public function onLoginFieldType(LoginFieldTypeEvent $event)
    {
        //switch the login form to allow non-email user names
        $event->setUseEmailField(false);
    }

    public function onLoginGetUser(LoginGetUserEvent $event)
    {
        $portalUser = null;
        $pimcoreUser = User::getByName($event->getUserName());
        if ($pimcoreUser && $pimcoreUser->getAdmin()) {
            $portalUser = $this->getOrCreatePortalUserByPimcoreUser($pimcoreUser);
            $event->setPortalUser($portalUser);
        }
    }

    public function onLoginCheckPassword(LoginCheckPasswordEvent $event)
    {
        $portalUser = $event->getPortalUser();
        if ($portalUser->getExternalUserId()) {
            $pimcoreUser = User::getByName($portalUser->getExternalUserId());
            $success = Authentication::isValidUser($pimcoreUser)
                && Authentication::verifyPassword(
                    $pimcoreUser,
                    $event->getPassword()
                );

            if ($success) {
                $event->setLoginValid(true);
            }
        }
    }

    public function onPasswordChangeable(LoginPasswordChangeableEvent $event)
    {
        /* If an external authentication service is used it might be needed to disable
         * the recover/change password functionality.
         *
         * In this example this is not necessary.
         */

        //$event->setPasswordChangeable(false);
    }

    protected function getOrCreatePortalUserByPimcoreUser(User $pimcoreUser)
    {
        // to make the portal engine work it is needed to create a portal user data object
        $portalUser = PortalUser::getByExternalUserId($pimcoreUser->getName(), 1);
        if (empty($portalUser)) {
            $portalUser = new PortalUser();
            $portalUser->setPimcoreUser($pimcoreUser->getId())
                ->setExternalUserId($pimcoreUser->getName())
                ->setAdmin(true)
                ->setKey($pimcoreUser->getName())
                ->setEmail($pimcoreUser->getEmail())
                ->setFirstname($pimcoreUser->getFirstname())
                ->setLastname($pimcoreUser->getLastname())
                ->setParent(Service::createFolderByPath(self::USER_FOLDER))
                ->setUsePimcoreUserPassword(true)
                ->setPublished(true)
                ->setKey(Service::getUniqueKey($portalUser))
                ->setPreferredLanguage($pimcoreUser->getLanguage());

            $portalUser->save();
        }

        return $portalUser;
    }
}

# add this to your container service definition
services:
    AppBundle\EventListener\PortalEngineAuthenticationSubscriber:
        tags:
            - { name: kernel.event_subscriber }