diff --git a/typo3/sysext/backend/Classes/Controller/MfaController.php b/typo3/sysext/backend/Classes/Controller/MfaController.php index 1faf759161fed1dd7e4149a345c0718b84c2e633..adebc0f7c39f084aa9bbd271d80155d9dbf6248c 100644 --- a/typo3/sysext/backend/Classes/Controller/MfaController.php +++ b/typo3/sysext/backend/Classes/Controller/MfaController.php @@ -120,7 +120,8 @@ class MfaController extends AbstractMfaController */ protected function verifyAction(ServerRequestInterface $request, MfaProviderManifestInterface $mfaProvider): ResponseInterface { - $propertyManager = MfaProviderPropertyManager::create($mfaProvider, $this->getBackendUser()); + $backendUser = $this->getBackendUser(); + $propertyManager = MfaProviderPropertyManager::create($mfaProvider, $backendUser); // Check if the provider can process the request and is not temporarily blocked if (!$mfaProvider->canProcess($request) || $mfaProvider->isLocked($propertyManager)) { @@ -150,7 +151,8 @@ class MfaController extends AbstractMfaController $this->log('Multi-factor authentication successful for user ###USERNAME###'); // If verified, store this information in the session // and initiate a redirect back to the login view. - $this->getBackendUser()->setAndSaveSessionData('mfa', true); + $backendUser->setAndSaveSessionData('mfa', true); + $backendUser->handleUserLoggedIn($request); return new RedirectResponse( $this->uriBuilder->buildUriWithRedirect('login', [], RouteRedirect::createFromRequest($request)) ); diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php index d1f47b6b48c9f6c967f68e7b17aacd0e8d01ae16..733754ef0d48cc9469d7a7c4768b9fd44a04be88 100644 --- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php @@ -2092,30 +2092,44 @@ class BackendUserAuthentication extends AbstractUserAuthentication $this->fetchGroupData(); // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values. $this->backendSetUC(); - if ($this->loginSessionStarted) { - // Also, if there is a recovery link set, unset it now - // this will be moved into its own Event at a later stage. - // If a token was set previously, this is now unset, as it was now possible to log-in - if ($this->user['password_reset_token'] ?? '') { - GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable($this->user_table) - ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]); - } + if ($this->loginSessionStarted && !($this->getSessionData('mfa') ?? false)) { + // Handling user logged in. By checking for the mfa session key, it's ensured, the + // handling is only done once, since MfaController does the handling on its own. + $this->handleUserLoggedIn(); + } + } - $event = new AfterUserLoggedInEvent($this, $request); - GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch($event); - // Process hooks - $hooks = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['backendUserLogin'] ?? []; - if (!empty($hooks)) { - trigger_error( - '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_userauthgroup.php\'][\'backendUserLogin\'] will be removed in TYPO3 v13.0. Use the PSR-14 "AfterUserLoggedInEvent" instead.', - E_USER_DEPRECATED - ); - } - foreach ($hooks as $_funcRef) { - $_params = ['user' => $this->user]; - GeneralUtility::callUserFunction($_funcRef, $_params, $this); - } + /** + * Is called after a user has sucesfully logged in. So either by using only one factor + * (e.g. username/password) or after the multi-factor authentication process has been passed. + * + * @internal + */ + public function handleUserLoggedIn(ServerRequestInterface $request = null): void + { + // Also, if there is a recovery link set, unset it now + // this will be moved into its own Event at a later stage. + // If a token was set previously, this is now unset, as it was now possible to log-in + if ($this->user['password_reset_token'] ?? '') { + GeneralUtility::makeInstance(ConnectionPool::class) + ->getConnectionForTable($this->user_table) + ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]); + } + + $event = new AfterUserLoggedInEvent($this, $request); + GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch($event); + + // Process hooks + $hooks = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['backendUserLogin'] ?? []; + if (!empty($hooks)) { + trigger_error( + '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_userauthgroup.php\'][\'backendUserLogin\'] will be removed in TYPO3 v13.0. Use the PSR-14 "AfterUserLoggedInEvent" instead.', + E_USER_DEPRECATED + ); + } + foreach ($hooks as $_funcRef) { + $_params = ['user' => $this->user]; + GeneralUtility::callUserFunction($_funcRef, $_params, $this); } }