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();
}