From d9c29986ac7385c7633f266124251a389994a3bd Mon Sep 17 00:00:00 2001 From: Oliver Bartsch <bo@cedev.de> Date: Thu, 6 Jul 2023 14:15:56 +0200 Subject: [PATCH] [BUGFIX] Add webhook message for failed mfa attempts In case a user did not pass necessary multi-factor authentication, this is handled as a login failure. Therefore, a webhook is now triggered for this scenario, like done for login failures of the first factor (usually username / password), providing basic information about the user and the used MFA provider. Resolves: #101263 Related: #100129 Releases: main, 12.4 Change-Id: I56b79a74d291beb94d78bb42305dcfba86ecaa26 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79825 Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: core-ci <typo3@b13.com> Tested-by: Benjamin Franzke <ben@bnf.dev> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Benjamin Franzke <ben@bnf.dev> --- .../Classes/Controller/MfaController.php | 2 +- .../Event/MfaVerificationFailedEvent.php | 9 ++- .../MfaVerificationErrorOccurredMessage.php | 67 +++++++++++++++++++ .../Private/Language/locallang_db.xlf | 3 + 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 typo3/sysext/webhooks/Classes/Message/MfaVerificationErrorOccurredMessage.php diff --git a/typo3/sysext/backend/Classes/Controller/MfaController.php b/typo3/sysext/backend/Classes/Controller/MfaController.php index adebc0f7c39f..0bf1ccd734e8 100644 --- a/typo3/sysext/backend/Classes/Controller/MfaController.php +++ b/typo3/sysext/backend/Classes/Controller/MfaController.php @@ -136,7 +136,7 @@ class MfaController extends AbstractMfaController error: SystemLogErrorClassification::SECURITY_NOTICE ); $this->eventDispatcher->dispatch( - new MfaVerificationFailedEvent($request, $propertyManager) + new MfaVerificationFailedEvent($request, $propertyManager, $mfaProvider) ); // If failed, initiate a redirect back to the auth view return new RedirectResponse($this->uriBuilder->buildUriWithRedirect( diff --git a/typo3/sysext/core/Classes/Authentication/Event/MfaVerificationFailedEvent.php b/typo3/sysext/core/Classes/Authentication/Event/MfaVerificationFailedEvent.php index ebc3cf1a11e4..e2f0365fb727 100644 --- a/typo3/sysext/core/Classes/Authentication/Event/MfaVerificationFailedEvent.php +++ b/typo3/sysext/core/Classes/Authentication/Event/MfaVerificationFailedEvent.php @@ -19,6 +19,7 @@ namespace TYPO3\CMS\Core\Authentication\Event; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication; +use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifestInterface; use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderPropertyManager; /** @@ -29,6 +30,7 @@ final class MfaVerificationFailedEvent extends AbstractAuthenticationFailedEvent public function __construct( private readonly ServerRequestInterface $request, private readonly MfaProviderPropertyManager $propertyManager, + private readonly MfaProviderManifestInterface $mfaProvider, ) { parent::__construct($this->request); } @@ -40,11 +42,16 @@ final class MfaVerificationFailedEvent extends AbstractAuthenticationFailedEvent public function getProviderIdentifier(): string { - return $this->propertyManager->getIdentifier(); + return $this->mfaProvider->getIdentifier(); } public function getProviderProperties(): array { return $this->propertyManager->getProperties(); } + + public function isProviderLocked(): bool + { + return $this->mfaProvider->isLocked($this->propertyManager); + } } diff --git a/typo3/sysext/webhooks/Classes/Message/MfaVerificationErrorOccurredMessage.php b/typo3/sysext/webhooks/Classes/Message/MfaVerificationErrorOccurredMessage.php new file mode 100644 index 000000000000..de5f1391195a --- /dev/null +++ b/typo3/sysext/webhooks/Classes/Message/MfaVerificationErrorOccurredMessage.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Webhooks\Message; + +use Psr\Http\Message\UriInterface; +use TYPO3\CMS\Core\Attribute\WebhookMessage; +use TYPO3\CMS\Core\Authentication\Event\MfaVerificationFailedEvent; +use TYPO3\CMS\Core\Messaging\WebhookMessageInterface; + +/** + * @internal not part of TYPO3's Core API + */ +#[WebhookMessage( + identifier: 'typo3/mfa-error', + description: 'LLL:EXT:webhooks/Resources/Private/Language/locallang_db.xlf:sys_webhook.webhook_type.typo3-mfa-error' +)] +final class MfaVerificationErrorOccurredMessage implements WebhookMessageInterface +{ + public function __construct( + private readonly bool $isFrontend, + private readonly UriInterface $url, + private readonly array $details, + ) { + } + + public function jsonSerialize(): array + { + return [ + 'context' => $this->isFrontend ? 'frontend' : 'backend', + 'url' => (string)$this->url, + 'details' => $this->details, + ]; + } + + public static function createFromEvent(MfaVerificationFailedEvent $event): self + { + $user = $event->getUser(); + + return new self( + $event->isFrontendAttempt(), + $event->getRequest()->getUri(), + [ + 'user' => [ + 'id' => $user->user[$user->userid_column], + 'name' => $user->user[$user->username_column], + ], + 'provider' => $event->getProviderIdentifier(), + 'isLocked' => $event->isProviderLocked(), + ] + ); + } +} diff --git a/typo3/sysext/webhooks/Resources/Private/Language/locallang_db.xlf b/typo3/sysext/webhooks/Resources/Private/Language/locallang_db.xlf index 1977525a2082..29f890cc3d96 100644 --- a/typo3/sysext/webhooks/Resources/Private/Language/locallang_db.xlf +++ b/typo3/sysext/webhooks/Resources/Private/Language/locallang_db.xlf @@ -73,6 +73,9 @@ <trans-unit id="sys_webhook.webhook_type.typo3-login-error" resname="sys_webhook.webhook_type.typo3-login-error"> <source>... when an error occurs on log in</source> </trans-unit> + <trans-unit id="sys_webhook.webhook_type.typo3-mfa-error" resname="sys_webhook.webhook_type.typo3-mfa-error"> + <source>... when an error occurs on multi-factor authentication</source> + </trans-unit> <trans-unit id="sys_webhook.webhook_type.typo3-file-added" resname="sys_webhook.webhook_type.typo3-file-added"> <source>... when a file is added</source> </trans-unit> -- GitLab