Skip to content

Commit 0cd8e1f

Browse files
committed
Automatically disable 2FA in developer mode, with optional toggle to fall back.
1 parent 41288f5 commit 0cd8e1f

File tree

4 files changed

+48
-27
lines changed

4 files changed

+48
-27
lines changed

Plugin/BypassTwoFactorAuth.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
class BypassTwoFactorAuth
1515
{
1616
const XML_PATH_CONFIG_ENABLE = 'twofactorauth/general/enable';
17-
const XML_PATH_CONFIG_DISABLE_DEV_2FA = 'twofactorauth/general/disable_developer_auth';
17+
const XML_PATH_CONFIG_ENABLE_FOR_API_TOKEN_GENERATION = 'twofactorauth/general/enable_for_api_token_generation';
18+
const XML_PATH_CONFIG_DISABLE_IN_DEVELOPER_MODE = 'twofactorauth/general/disable_in_developer_mode';
1819

1920
/** @var ScopeConfigInterface */
2021
private $scopeConfig;
@@ -37,11 +38,12 @@ public function __construct(
3738

3839
/**
3940
* Enables the bypass of 2FA for admin access.
40-
* This can be useful within development & integration environments.
41+
* This can be useful for within development & integration environments.
4142
*
4243
* If 2FA is enabled, return the original result.
43-
* If 2FA is disabled, always return true so all requests bypass 2FA.
44-
* If 2FA is disabled only for developer mode, return true when in developer mode to bypass 2FA.
44+
* If developer mode is enabled, 2FA is disabled unless "Disable 2FA in developer mode" is set to No.
45+
*
46+
* Returning true in this function bypasses 2FA.
4547
*
4648
* NOTE: Always keep 2FA enabled within production environments for security purposes.
4749
*
@@ -53,17 +55,16 @@ public function afterIsGranted(
5355
TfaSession $subject,
5456
$result
5557
): bool {
56-
// 2FA is always disabled.
57-
if (!$this->scopeConfig->isSetFlag(self::XML_PATH_CONFIG_ENABLE)) {
58-
return true;
59-
}
58+
$is2faEnabled = $this->scopeConfig->isSetFlag(self::XML_PATH_CONFIG_ENABLE);
59+
$isDeveloperMode = $this->appState->getMode() == State::MODE_DEVELOPER;
60+
$alwaysDisableInDeveloperMode = $this->scopeConfig->isSetFlag(self::XML_PATH_CONFIG_DISABLE_IN_DEVELOPER_MODE);
6061

61-
// 2FA is disabled only for developer mode.
62-
if ($this->scopeConfig->isSetFlag(self::XML_PATH_CONFIG_DISABLE_DEV_2FA)
63-
&& $this->appState->getMode() == State::MODE_DEVELOPER) {
64-
return true;
62+
if ($isDeveloperMode && $alwaysDisableInDeveloperMode) {
63+
$is2faEnabled = false;
6564
}
6665

67-
return $result;
66+
return $is2faEnabled
67+
? $result
68+
: true;
6869
}
6970
}

Plugin/BypassTwoFactorAuthForApiTokenGeneration.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use Closure;
77
use Magento\Framework\App\Config\ScopeConfigInterface;
8+
use Magento\Framework\App\State;
89
use Magento\Framework\Exception\AuthenticationException;
910
use Magento\Framework\Exception\InputException;
1011
use Magento\Framework\Exception\LocalizedException;
@@ -17,30 +18,39 @@
1718
*/
1819
class BypassTwoFactorAuthForApiTokenGeneration
1920
{
20-
const XML_PATH_CONFIG_ENABLE_FOR_API_TOKEN_GENERATION = 'twofactorauth/general/enable_for_api_token_generation';
21+
/** @var AdminTokenServiceInterface */
22+
private $adminTokenService;
2123

2224
/** @var ScopeConfigInterface */
2325
private $scopeConfig;
2426

25-
/** @var AdminTokenServiceInterface */
26-
private $adminTokenService;
27+
/** @var State */
28+
private $appState;
2729

2830
/**
2931
* BypassTwoFactorAuthForApiTokenGeneration constructor.
3032
* @param AdminTokenServiceInterface $adminTokenService
3133
* @param ScopeConfigInterface $scopeConfig
34+
* @param State $appState
3235
*/
3336
public function __construct(
3437
AdminTokenServiceInterface $adminTokenService,
35-
ScopeConfigInterface $scopeConfig
38+
ScopeConfigInterface $scopeConfig,
39+
State $appState
3640
) {
3741
$this->scopeConfig = $scopeConfig;
3842
$this->adminTokenService = $adminTokenService;
43+
$this->appState = $appState;
3944
}
4045

4146
/**
4247
* Enables the bypass of 2FA for API token generation.
43-
* This can be useful for third-party vendors during module development.
48+
* This can be useful for within development & integration environments.
49+
*
50+
* If 2FA is enabled, return the original result.
51+
* If developer mode is enabled, 2FA is disabled unless "Disable 2FA in developer mode" is set to No.
52+
*
53+
* Calling createAdminAccessToken within this function bypasses 2FA.
4454
*
4555
* NOTE: Always keep 2FA enabled within production environments for security purposes.
4656
*
@@ -59,7 +69,19 @@ public function aroundCreateAdminAccessToken(
5969
$username,
6070
$password
6171
): string {
62-
return $this->scopeConfig->isSetFlag(self::XML_PATH_CONFIG_ENABLE_FOR_API_TOKEN_GENERATION)
72+
$is2faEnabled = $this->scopeConfig->isSetFlag(
73+
BypassTwoFactorAuth::XML_PATH_CONFIG_ENABLE_FOR_API_TOKEN_GENERATION
74+
);
75+
$isDeveloperMode = $this->appState->getMode() == State::MODE_DEVELOPER;
76+
$alwaysDisableInDeveloperMode = $this->scopeConfig->isSetFlag(
77+
BypassTwoFactorAuth::XML_PATH_CONFIG_DISABLE_IN_DEVELOPER_MODE
78+
);
79+
80+
if ($isDeveloperMode && $alwaysDisableInDeveloperMode) {
81+
$is2faEnabled = false;
82+
}
83+
84+
return $is2faEnabled
6385
? $proceed($username, $password)
6486
: $this->adminTokenService->createAdminAccessToken($username, $password);
6587
}

etc/adminhtml/system.xml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@
88
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
99
<comment>Warning: Enabling 2FA will immediately prompt admin user for OTP code.</comment>
1010
</field>
11-
<field id="disable_developer_auth" translate="label" type="select" sortOrder="150" showInDefault="1" canRestore="1">
12-
<label>Disable Developer Mode 2FA</label>
13-
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
14-
<comment>Disable 2FA only when Magento is in developer mode.</comment>
15-
<depends>
16-
<field id="enable">1</field>
17-
</depends>
18-
</field>
1911
<field id="enable_for_api_token_generation" translate="label" type="select" sortOrder="200" showInDefault="1" canRestore="1">
2012
<label>Enable 2FA for API Token Generation</label>
2113
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
2214
</field>
15+
<field id="disable_in_developer_mode" translate="label" type="select" sortOrder="150" showInDefault="1" canRestore="1">
16+
<label>Disable 2FA in Developer Mode</label>
17+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
18+
<comment>When set to No the above settings are used, otherwise 2FA is disabled in developer mode.</comment>
19+
</field>
2320
<field id="force_providers">
2421
<depends>
2522
<field id="enable">1</field>

etc/config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<general>
66
<enable>1</enable>
77
<enable_for_api_token_generation>1</enable_for_api_token_generation>
8+
<disable_in_developer_mode>1</disable_in_developer_mode>
89
</general>
910
</twofactorauth>
1011
</default>

0 commit comments

Comments
 (0)