{include file='header' __disableAds=true __sidebarLeftHasMenu=true}
+{if $requiresMultifactor}
+ <woltlab-core-notice type="warning">{lang}wcf.user.security.requiresMultifactor{/lang}</woltlab-core-notice>
+{/if}
+
<section class="section" id="section_multifactor">
<header class="sectionHeader">
<h2 class="sectionTitle">{lang}wcf.user.security.multifactor{/lang}</h2>
--- /dev/null
+<?php
+
+namespace wcf\http\middleware;
+
+use Laminas\Diactoros\Response\RedirectResponse;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use wcf\form\MultifactorManageForm;
+use wcf\http\Helper;
+use wcf\page\AccountSecurityPage;
+use wcf\system\request\LinkHandler;
+use wcf\system\request\RequestHandler;
+use wcf\system\WCF;
+
+/**
+ * Checks whether the user is required to set up the multi-factor authentication.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+final class CheckForMultifactorRequirement implements MiddlewareInterface
+{
+ private const ALLOWED_CONTROLLERS = [
+ AccountSecurityPage::class,
+ MultifactorManageForm::class,
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ {
+ if (
+ $this->multifactorRequired()
+ && !$this->requestCanBypassMultifactor($request)
+ ) {
+ return new RedirectResponse(
+ LinkHandler::getInstance()->getControllerLink(AccountSecurityPage::class)
+ );
+ }
+
+ return $handler->handle($request);
+ }
+
+ private function multifactorRequired(): bool
+ {
+ return WCF::getUser()->userID
+ && WCF::getUser()->requiresMultifactor()
+ && !WCF::getUser()->multifactorActive;
+ }
+
+ private function requestCanBypassMultifactor(ServerRequestInterface $request): bool
+ {
+ $controller = RequestHandler::getInstance()->getActiveRequest()->getClassName();
+ if (\in_array($controller, self::ALLOWED_CONTROLLERS, true)) {
+ return true;
+ }
+
+ if (RequestHandler::getInstance()->getActiveRequest()->isAvailableDuringOfflineMode()) {
+ return true;
+ }
+
+ if (Helper::isAjaxRequest($request)) {
+ return true;
+ }
+
+ return false;
+ }
+}
use wcf\http\Helper;
use wcf\system\request\LinkHandler;
use wcf\system\request\RequestHandler;
-use wcf\system\user\multifactor\TMultifactorRequirementEnforcer;
use wcf\system\WCF;
use wcf\system\WCFACP;
use wcf\util\HeaderUtil;
*/
final class EnforceAcpAuthentication implements MiddlewareInterface
{
- use TMultifactorRequirementEnforcer;
-
private const ALLOWED_CONTROLLERS = [
LoginForm::class,
ReauthenticationForm::class,
return $this->handleReauthentication($request);
}
- $this->enforceMultifactorAuthentication();
-
// force debug mode if in ACP and authenticated
WCFACP::overrideDebugMode();
'activeSessions' => $this->activeSessions,
'multifactorMethods' => $this->multifactorMethods,
'enabledMultifactorMethods' => $this->enabledMultifactorMethods,
+ 'requiresMultifactor' => WCF::getUser()->requiresMultifactor() && !WCF::getUser()->multifactorActive,
]);
}
use wcf\http\middleware\AddAcpSecurityHeaders;
use wcf\http\middleware\CheckForEnterpriseNonOwnerAccess;
use wcf\http\middleware\CheckForExpiredAppEvaluation;
+use wcf\http\middleware\CheckForMultifactorRequirement;
use wcf\http\middleware\CheckForOfflineMode;
use wcf\http\middleware\CheckHttpMethod;
use wcf\http\middleware\CheckSystemEnvironment;
new CheckForEnterpriseNonOwnerAccess(),
new CheckForExpiredAppEvaluation(),
new CheckForOfflineMode(),
+ new CheckForMultifactorRequirement(),
new JsonBody(),
new TriggerBackgroundQueue(),
new HandleExceptions(),
* @copyright 2001-2020 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 5.4
+ * @deprecated 6.1
*/
trait TMultifactorRequirementEnforcer
{
<item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions"><![CDATA[Erlaubte Dateiendungen]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxCount"><![CDATA[Maximale Dateianhänge]]></item>
<item name="wcf.acp.group.requireMultifactor"><![CDATA[Mehrfaktor-Authentifizierung erzwingen]]></item>
- <item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Benutzer, die Mitglied dieser Benutzergruppe sind, können die Mehrfaktor-Authentifizierung nicht deaktivieren und können besonders geschützte Bereiche erst betreten, wenn sie die Mehrfaktor-Authentifizierung eingerichtet haben.]]></item>
+ <item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Benutzer, die Mitglied dieser Benutzergruppe sind, müssen die Mehrfaktor-Authentifizierung einrichten.]]></item>
<item name="wcf.acp.group.option.admin.user.canExportGdprData"><![CDATA[Kann persönliche Daten (DSGVO) exportieren]]></item>
<item name="wcf.acp.group.option.admin.user.canExportGdprData.description"><![CDATA[Der Export gemäß der europäischen Datenschutz-Grundverordnung (DSGVO) enthält detaillierte persönliche Daten des jeweiligen Benutzers. Eine Filterung der im Export enthaltenen Information auf Basis der Zugriffsrechte des Administrators findet <strong>nicht</strong> statt und kann unter Umständen Informationen enthalten, die einem Administrator auf andere Weise nicht zugänglich wären.]]></item>
</category>
<item name="wcf.user.security.multifactor.totp.success.add"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Dein{else}Ihr{/if} Smartphone <strong>{$deviceName}</strong> wurde erfolgreich hinterlegt.]]></item>
<item name="wcf.user.security.multifactor.totp.success.delete"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Dein{else}Ihr{/if} Smartphone <strong>{$deviceName}</strong> wurde erfolgreich entfernt.]]></item>
<item name="wcf.user.security.multifactor.totp.useTime"><![CDATA[Zuletzt Benutzt]]></item>
- <item name="wcf.user.security.requiresMultifactor"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} Mitglied einer Benutzergruppe, die verpflichtet ist, die Mehrfaktor-Authentifizierung zu nutzen. Bevor {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} auf diese Seite zugreifen {if LANGUAGE_USE_INFORMAL_VARIANT}darfst, musst du{else}dürfen, müssen Sie{/if} <a href="{link controller='AccountSecurity' forceFrontend=true}#section_multifactor{/link}">die Mehrfaktor-Authentifizierung aktivieren</a>.]]></item>
+ <item name="wcf.user.security.requiresMultifactor"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} Mitglied einer Benutzergruppe, die verpflichtet ist, die Mehrfaktor-Authentifizierung zu nutzen.]]></item>
<item name="wcf.user.security.sessionName"><![CDATA[{if $session->getUserAgent()->getBrowser()}{$session->getUserAgent()->getBrowser()}{if $session->getUserAgent()->getOS()} auf {$session->getUserAgent()->getOS()}{/if}{else}Unbekanntes Gerät{/if}]]></item>
<item name="wcf.user.security.multifactor.otherOptions"><![CDATA[Andere Option wählen]]></item>
</category>
<item name="wcf.acp.group.option.user.signature.attachment.allowedExtensions"><![CDATA[Allowed Attachment File Extensions]]></item>
<item name="wcf.acp.group.option.user.signature.attachment.maxCount"><![CDATA[Maximum Attachments]]></item>
<item name="wcf.acp.group.requireMultifactor"><![CDATA[Require Multi-factor Authentication]]></item>
- <item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Users that are members of this user group may not disable multi-factor authentication. They will also be required to set up multi-factor authentication before they may enter protected areas.]]></item>
+ <item name="wcf.acp.group.requireMultifactor.description"><![CDATA[Users that are members of this user group are required to set up multi-factor authentication.]]></item>
<item name="wcf.acp.group.option.admin.user.canExportGdprData"><![CDATA[Can export personal data (GDPR)]]></item>
<item name="wcf.acp.group.option.admin.user.canExportGdprData.description"><![CDATA[The export according to the European General Data Protection Regulation (GDPR) contains detailed personal data of the respective user. The export <strong>will not</strong> be filtered according to the administrator’s permissions and may contain information that would be inaccessible otherwise.]]></item>
</category>
<item name="wcf.user.security.multifactor.totp.success.add"><![CDATA[Your smartphone <strong>{$deviceName}</strong> has successfully been added.]]></item>
<item name="wcf.user.security.multifactor.totp.success.delete"><![CDATA[Your smartphone <strong>{$deviceName}</strong> has successfully been removed.]]></item>
<item name="wcf.user.security.multifactor.totp.useTime"><![CDATA[Last Used]]></item>
- <item name="wcf.user.security.requiresMultifactor"><![CDATA[You are a member of a user group that is required to use multi-factor authentication. Before you may access this page you must <a href="{link controller='AccountSecurity' forceFrontend=true}#section_multifactor{/link}">enable multi-factor authentication</a>.]]></item>
+ <item name="wcf.user.security.requiresMultifactor"><![CDATA[You are a member of a user group that is required to use multi-factor authentication.]]></item>
<item name="wcf.user.security.sessionName"><![CDATA[{if $session->getUserAgent()->getBrowser()}{$session->getUserAgent()->getBrowser()}{if $session->getUserAgent()->getOS()} on {$session->getUserAgent()->getOS()}{/if}{else}Unknown Device{/if}]]></item>
<item name="wcf.user.security.multifactor.otherOptions"><![CDATA[Select another option]]></item>
</category>