0

I am working on SSO for the Magento admin. Everything below appears to work through the processLogin() event (which is triggered by the controllers execute() method. Once processLogin() is returned, the user is redirected to via:

if ($this->adminAuthSession->isLoggedIn()) {
    return $this->resultRedirectFactory->create()->setUrl($this->getUrl('admin'));
}

isLoggedIn() returns true. However, the user is returned to the admin login page and shown the message: "Your current session has expired."


The Code

etc/adminhtml/routes.xml: Define admin routes

<?xml version="1.0"?>
     <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="microsoft_sso" frontName="microsoft_sso">
            <module name="Etre_MicrosoftAdminSso" before="Magento_Backend"/>
        </route>
    </router>
</config>

etc/adminhtml/di.xml: Extend adminAuthentication so that we can make some of our SSO admin routes public for authentication

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Backend\App\AbstractAction">
        <!--
        /**
         * Make SSO login route public by extend Magento\Backend\App\Action\Plugin\Authentication by it's original
         * plugin name of adminAuthentication
         */
         -->
        <plugin name="adminAuthentication"
                type="Etre\MicrosoftAdminSso\Plugin\Backend\PublicActions"/>
    </type>
</config>

Controller/Adminhtml/Sso/Login.php: Handle SSO authentication

Only relevant methods included.

class Login extends \Magento\User\Controller\Adminhtml\Auth
{
public function __construct(
    \Magento\Backend\App\Action\Context $context,
    \Magento\User\Model\UserFactory $userFactory,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    Data $ssoHelper,
    \Magento\Framework\DataObjectFactory $objectFactory,
    \Magento\Backend\Model\Auth\Session\Proxy $adminAuthSession,
    \Magento\Backend\Model\Session\AdminConfig $adminConfig,
    \Magento\Framework\App\State $appState,
    \Magento\Framework\ObjectManager\ConfigLoaderInterface $configLoader,
    \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager,
    \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
) {
    parent::__construct($context, $userFactory);
    $this->_userFactory = $userFactory;
    $this->ssoHelper = $ssoHelper;
    $this->scopeConfig = $scopeConfig;
    $this->backendSession= $context->getSession();
    $this->objectFactory = $objectFactory;
    $this->adminAuthSession = $adminAuthSession;
    $this->adminConfig = $adminConfig;
    $this->appState = $appState;
    $this->configLoader = $configLoader;
    $this->cookieManager = $cookieManager;
    $this->cookieMetadataFactory = $cookieMetadataFactory;
}

private function processLogin(\ArrayAccess $userInfo): void
{
//        $this->_request->setPathInfo('/admin');
//        $this->appState->setAreaCode($areaCode);
//        $this->_objectManager->configure($this->_configLoader->load($areaCode));

    $user = $this->_userFactory->create()->load($userInfo->getUniqueName(), 'email');

    $session = $this->adminAuthSession;
    $session->setUser($user);
    $session->processLogin();

    if ($session->isLoggedIn() && $session->getSessionId()) {
        $session->prolong();
    }
}

...

}

Original, alternative processLogin() tried:

private function processLogin(\ArrayAccess $userInfo): void
{
    if (!$userInfo->hasUniqueName()) {
        throw new AuthorizationException('Microsoft failed to provide your username');
    }

    $user = $this->_userFactory->create()->load($userInfo->getUniqueName(), 'email');

    $isActive = (bool)$user->getIsActive();

    if (!$isActive) {
        throw new AuthorizationException('This account does not exist or is not currently active.');
    }

    $this->adminAuthSession->setUser($user);
    $this->adminAuthSession->processLogin();
}

1 Answer 1

0

The problem was that I needed to inject my $user into \Magento\Backend\Model\Auth\Session so that it could be referenced by \Magento\Security\Model\AdminSessionsManager()->processLogin().

My refactored code is below.

$this->authSession is dependency injected as \Magento\Backend\Model\Auth\Session and $this-sessionManager as \Magento\Security\Model\AdminSessionsManager

/**
 * @param \ArrayAccess $userInfo
 * @return void
 * @throws AuthorizationException
 */
private function processLogin(\ArrayAccess $userInfo): void
{
    $this->loadUser($userInfo->getUniqueName())
        ->makeAdminSession();

    if (!$this->isLoggedIn()) {
        throw new AuthorizationException(__('Login Failed. You may try providing a username or password.'));
    }
}

/**
 * Create a logged in user session
 */
private function makeAdminSession(): void
{
    $this->authSession->setUser($this->user);
    $this->sessionManager->processLogin();
}

/**
 * Fetch user model by email
 *
 * @param string $email
 * @return $this
 * @throws AuthorizationException
 */
private function loadUser(string $email): Login
{
    $this->user = $this->_userFactory->create()->load($email, 'email');

    $userLoaded = (bool) $this->user->getId();
    if (!$userLoaded) {
        throw new AuthorizationException(__('Could not find a user associated with email %1', $email));
    }

    return $this;
}


/**
 * Check if user is logged in
 *
 * @return bool
 */
private function isLoggedIn(): bool
{
    return $this->sessionManager->getCurrentSession()->isLoggedInStatus();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.