Skip to content

Commit d9a4334

Browse files
committed
Merge branch 'magento:develop' into develop
2 parents 5ddbc7c + e4aea96 commit d9a4334

File tree

12 files changed

+244
-18
lines changed

12 files changed

+244
-18
lines changed

ReCaptchaUser/Test/Integration/LoginFormTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ private function checkSuccessfulGetResponse($shouldContainReCaptcha = false): vo
179179
$this->getRequest()->setUri($this->backendUrl->getUrl('admin'));
180180

181181
$this->dispatch('backend/admin/auth/login');
182+
183+
if ($this->getResponse()->getHeader('Location')) {
184+
$this->dispatch($this->getResponse()->getHeader('Location')->uri()->getPath());
185+
}
186+
182187
$content = $this->getResponse()->getBody();
183188

184189
self::assertNotEmpty($content);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
9+
<policies>
10+
<policy id="frame-src">
11+
<values>
12+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
13+
</values>
14+
</policy>
15+
<policy id="script-src">
16+
<values>
17+
<value id="gstatic_com" type="host">https://www.gstatic.com/recaptcha/</value>
18+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
19+
</values>
20+
</policy>
21+
</policies>
22+
</csp_whitelist>
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
9+
<policies>
10+
<policy id="frame-src">
11+
<values>
12+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
13+
</values>
14+
</policy>
15+
<policy id="script-src">
16+
<values>
17+
<value id="gstatic_com" type="host">https://www.gstatic.com/recaptcha/</value>
18+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
19+
</values>
20+
</policy>
21+
</policies>
22+
</csp_whitelist>
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
9+
<policies>
10+
<policy id="frame-src">
11+
<values>
12+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
13+
</values>
14+
</policy>
15+
<policy id="script-src">
16+
<values>
17+
<value id="gstatic_com" type="host">https://www.gstatic.com/recaptcha/</value>
18+
<value id="google_com" type="host">https://www.google.com/recaptcha/</value>
19+
</values>
20+
</policy>
21+
</policies>
22+
</csp_whitelist>
23+

TwoFactorAuth/Model/Provider/Engine/Google.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ public function __construct(
9898
private function generateSecret(): string
9999
{
100100
$secret = random_bytes(128);
101-
return preg_replace('/[^A-Za-z0-9]/', '', Base32::encode($secret));
101+
// seed for iOS devices to avoid errors with barcode
102+
$seed = 'abcd';
103+
104+
return preg_replace('/[^A-Za-z0-9]/', '', Base32::encode($seed . $secret));
102105
}
103106

104107
/**

TwoFactorAuth/Test/Api/GoogleAuthenticateTest.php

+132-9
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,22 @@
77

88
namespace Magento\TwoFactorAuth\Test\Api;
99

10+
use Magento\Framework\HTTP\ClientInterface;
11+
use Magento\Framework\Serialize\SerializerInterface;
12+
use Magento\Framework\UrlInterface;
1013
use Magento\Framework\Webapi\Rest\Request;
14+
use Magento\Integration\Model\Oauth\TokenFactory;
15+
use Magento\Integration\Model\ResourceModel\Oauth\Token as TokenResource;
1116
use Magento\TestFramework\Helper\Bootstrap;
1217
use Magento\TestFramework\TestCase\WebapiAbstract;
1318
use Magento\TwoFactorAuth\Api\TfaInterface;
1419
use Magento\TwoFactorAuth\Model\Provider\Engine\Google;
1520
use Magento\User\Model\UserFactory;
1621
use OTPHP\TOTP;
1722

23+
/**
24+
* Class checks google authentication behaviour
25+
*/
1826
class GoogleAuthenticateTest extends WebapiAbstract
1927
{
2028
const SERVICE_VERSION = 'V1';
@@ -37,18 +45,53 @@ class GoogleAuthenticateTest extends WebapiAbstract
3745
*/
3846
private $tfa;
3947

48+
/**
49+
* @var ClientInterface
50+
*/
51+
private $client;
52+
53+
/**
54+
* @var UrlInterface
55+
*/
56+
private $url;
57+
58+
/**
59+
* @var SerializerInterface
60+
*/
61+
private $json;
62+
63+
/**
64+
* @var TokenResource
65+
*/
66+
private $tokenResource;
67+
68+
/**
69+
* @var TokenFactory
70+
*/
71+
private $tokenFactory;
72+
73+
/**
74+
* @inheritdoc
75+
*/
4076
protected function setUp(): void
4177
{
4278
$objectManager = Bootstrap::getObjectManager();
4379
$this->userFactory = $objectManager->get(UserFactory::class);
4480
$this->google = $objectManager->get(Google::class);
4581
$this->tfa = $objectManager->get(TfaInterface::class);
82+
$this->client = $objectManager->get(ClientInterface::class);
83+
$this->url = $objectManager->get(UrlInterface::class);
84+
$this->json = $objectManager->get(SerializerInterface::class);
85+
$this->tokenResource = $objectManager->get(TokenResource::class);
86+
$this->tokenFactory = $objectManager->get(TokenFactory::class);
4687
}
4788

4889
/**
4990
* @magentoApiDataFixture Magento/User/_files/user_with_custom_role.php
91+
*
92+
* @return void
5093
*/
51-
public function testInvalidCredentials()
94+
public function testInvalidCredentials(): void
5295
{
5396
$serviceInfo = $this->buildServiceInfo();
5497

@@ -80,8 +123,10 @@ public function testInvalidCredentials()
80123
/**
81124
* @magentoConfigFixture twofactorauth/general/force_providers duo_security
82125
* @magentoApiDataFixture Magento/User/_files/user_with_custom_role.php
126+
*
127+
* @return void
83128
*/
84-
public function testUnavailableProvider()
129+
public function testUnavailableProvider(): void
85130
{
86131
$serviceInfo = $this->buildServiceInfo();
87132

@@ -109,8 +154,10 @@ public function testUnavailableProvider()
109154
/**
110155
* @magentoConfigFixture twofactorauth/general/force_providers google
111156
* @magentoApiDataFixture Magento/User/_files/user_with_custom_role.php
157+
*
158+
* @return void
112159
*/
113-
public function testInvalidToken()
160+
public function testInvalidToken(): void
114161
{
115162
$userId = $this->getUserId();
116163
$serviceInfo = $this->buildServiceInfo();
@@ -141,8 +188,10 @@ public function testInvalidToken()
141188
/**
142189
* @magentoConfigFixture twofactorauth/general/force_providers google
143190
* @magentoApiDataFixture Magento/User/_files/user_with_custom_role.php
191+
*
192+
* @return void
144193
*/
145-
public function testNotConfiguredProvider()
194+
public function testNotConfiguredProvider(): void
146195
{
147196
$userId = $this->getUserId();
148197
$serviceInfo = $this->buildServiceInfo();
@@ -174,8 +223,10 @@ public function testNotConfiguredProvider()
174223
* @magentoConfigFixture twofactorauth/general/force_providers google
175224
* @magentoApiDataFixture Magento/User/_files/user_with_custom_role.php
176225
* @magentoConfigFixture twofactorauth/google/otp_window 120
226+
*
227+
* @return void
177228
*/
178-
public function testValidToken()
229+
public function testValidToken(): void
179230
{
180231
$userId = $this->getUserId();
181232
$otp = $this->getUserOtp();
@@ -195,6 +246,37 @@ public function testValidToken()
195246
self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $response);
196247
}
197248

249+
/**
250+
* @magentoConfigFixture default/oauth/access_token_lifetime/admin 1
251+
* @magentoConfigFixture twofactorauth/general/force_providers google
252+
*
253+
* @magentoApiDataFixture Magento/Webapi/_files/webapi_user.php
254+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
255+
*
256+
* @return void
257+
*/
258+
public function testAdminTokenLifetime(): void
259+
{
260+
$this->_markTestAsRestOnly();
261+
$this->tfa->getProviderByCode(Google::CODE)->activate($this->getUserId('webapi_user'));
262+
$otp = $this->getUserOtp('webapi_user');
263+
$serviceInfo = $this->buildServiceInfo();
264+
$requestData = [
265+
'otp' => $otp,
266+
'username' => 'webapi_user',
267+
'password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
268+
];
269+
$accessToken = $this->_webApiCall($serviceInfo, $requestData);
270+
$result = $this->doCustomerRequest($accessToken, 1);
271+
$this->assertContains('customer@example.com', $this->json->unserialize($result));
272+
$this->updateTokenCreatedTime($accessToken);
273+
$result = $this->doCustomerRequest($accessToken, 1);
274+
$this->assertContains(
275+
'The consumer isn\'t authorized to access %resources.',
276+
$this->json->unserialize($result)
277+
);
278+
}
279+
198280
/**
199281
* @return array
200282
*/
@@ -217,20 +299,61 @@ private function buildServiceInfo(): array
217299
];
218300
}
219301

220-
private function getUserId(): int
302+
/**
303+
* Get user id
304+
*
305+
* @param string $userName
306+
* @return int
307+
*/
308+
private function getUserId($userName = 'customRoleUser'): int
221309
{
222310
$user = $this->userFactory->create();
223-
$user->loadByUsername('customRoleUser');
311+
$user->loadByUsername($userName);
224312

225313
return (int)$user->getId();
226314
}
227315

228-
private function getUserOtp(): string
316+
/**
317+
* Get user otp
318+
*
319+
* @param string $userName
320+
* @return string
321+
*/
322+
private function getUserOtp($userName = 'customRoleUser'): string
229323
{
230324
$user = $this->userFactory->create();
231-
$user->loadByUsername('customRoleUser');
325+
$user->loadByUsername($userName);
232326
$totp = TOTP::create($this->google->getSecretCode($user));
233327

234328
return $totp->now();
235329
}
330+
331+
/**
332+
* Perform request to customers endpoint
333+
*
334+
* @param string $accessToken
335+
* @return string
336+
*/
337+
private function doCustomerRequest(string $accessToken, $customerId): string
338+
{
339+
$this->client->addHeader('Authorization', 'Bearer ' . $accessToken);
340+
$this->client->get($this->url->getBaseUrl() . 'rest/V1/customers/' . $customerId);
341+
342+
return $this->client->getBody();
343+
}
344+
345+
/**
346+
* Update token created time
347+
*
348+
* @param string $accessToken
349+
* @return void
350+
*/
351+
private function updateTokenCreatedTime(string $accessToken): void
352+
{
353+
$token = $this->tokenFactory->create();
354+
$token->loadByToken($accessToken);
355+
$createdAt = (new \DateTime('-1 day'))->format('Y-m-d H:i:s');
356+
$token->setCreatedAt($createdAt);
357+
$this->tokenResource->save($token);
358+
}
236359
}

TwoFactorAuth/Test/Integration/ControllerActionPredispatchTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public function testUnauthenticated(): void
9191
$this->dispatch('backend/admin/index/index');
9292
//Login controller redirects to full start-up URL
9393
$this->assertRedirect($this->stringContains('index'));
94-
$properUrl = $this->getResponse()->getHeader('Location')->getFieldValue();
94+
$properUrl = $this->getResponse()->getHeader('Location')->uri()->getPath();
9595

9696
//Login page must be rendered without redirects
9797
$this->getRequest()->setDispatched(false);

TwoFactorAuth/Test/Integration/Model/Provider/Engine/Authy/AuthenticateTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public function testAuthenticateValidRequest()
156156
'abc'
157157
);
158158

159-
self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $result);
159+
self::assertNotEmpty($result);
160160
}
161161

162162
/**
@@ -290,7 +290,7 @@ public function testCreateTokenWithOneTouch()
290290
Bootstrap::ADMIN_PASSWORD
291291
);
292292

293-
self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $result);
293+
self::assertNotEmpty($result);
294294
}
295295

296296
/**

TwoFactorAuth/Test/Integration/Model/Provider/Engine/DuoSecurity/AuthenticateTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ public function testVerifyValidRequest()
257257
$signature
258258
);
259259

260-
self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $token);
260+
self::assertNotEmpty($token);
261261
}
262262

263263
/**

TwoFactorAuth/Test/Integration/Model/Provider/Engine/U2fKey/AuthenticateTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public function testVerifyValidRequest()
238238
Bootstrap::ADMIN_PASSWORD,
239239
json_encode($verifyData)
240240
);
241-
self::assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $token);
241+
self::assertNotEmpty($token);
242242
}
243243

244244
/**

TwoFactorAuth/Test/Integration/UserConfigManagerTest.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ public function testShouldEncryptConfiguration(): void
170170
$encryptor = Bootstrap::getObjectManager()->create(EncryptorInterface::class);
171171

172172
/** @var ResourceConnection $resourceConnection */
173-
$connection = Bootstrap::getObjectManager()->get(ResourceConnection::class)
174-
->getConnection(ResourceConnection::DEFAULT_CONNECTION);
173+
$resourceConnection = Bootstrap::getObjectManager()->get(ResourceConnection::class);
174+
$connection = $resourceConnection->getConnection(ResourceConnection::DEFAULT_CONNECTION);
175175

176176
$configPayload = ['a' => 1, 'b' => 2];
177177

@@ -181,8 +181,10 @@ public function testShouldEncryptConfiguration(): void
181181
$configPayload
182182
);
183183

184+
$tfaUserConfig = $resourceConnection->getTableName('tfa_user_config');
185+
184186
$qry = $connection->select()
185-
->from('tfa_user_config', 'encoded_config')
187+
->from($tfaUserConfig, 'encoded_config')
186188
->where('user_id = ?', (int)$dummyUser->getId());
187189

188190
$res = $connection->fetchOne($qry);

0 commit comments

Comments
 (0)