‪TYPO3CMS  11.5
RecoveryCodesTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
25 
26 class ‪RecoveryCodesTest extends UnitTestCase
27 {
29 
30  protected function ‪setUp(): void
31  {
32  parent::setUp();
33 
35  $this->subject = GeneralUtility::makeInstance(RecoveryCodes::class, 'BE');
36  }
37 
38  protected function ‪tearDown(): void
39  {
41 
42  parent::tearDown();
43  }
44 
48  public function ‪generateRecoveryCodesTest(): void
49  {
50  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [
51  'className' => NoopPasswordHash::class,
52  'options' => [],
53  ];
54 
55  $codes = $this->subject->generateRecoveryCodes();
56 
57  self::assertCount(8, $codes);
58 
59  $plainCodes = array_keys($codes);
60  $hashedCodes = array_values($codes);
61  $hashInstance = (new ‪NoopPasswordHash());
62 
63  foreach ($hashedCodes as $key => $code) {
64  self::assertTrue($hashInstance->isValidSaltedPW($code));
65  self::assertTrue($hashInstance->checkPassword((string)$plainCodes[$key], $code));
66  }
67  }
68 
73  {
74  $this->expectException(\InvalidArgumentException::class);
75  $this->expectExceptionCode(1613666803);
76  $this->subject->generatePlainRecoveryCodes(6);
77  }
78 
86  public function ‪generatePlainRecoveryCodesTest(int $length, int $quantity): void
87  {
88  $recoveryCodes = $this->subject->generatePlainRecoveryCodes($length, $quantity);
89  self::assertCount($quantity, $recoveryCodes);
90  foreach ($recoveryCodes as $code) {
91  self::assertIsNumeric($code);
92  self::assertEquals($length, strlen($code));
93  }
94  }
95 
96  public function ‪generatePlainRecoveryCodesTestDataProvider(): \Generator
97  {
98  yield 'Default 8 codes with 8 chars' => [8, 8];
99  yield '8 codes with 10 chars' => [8, 10];
100  yield '10 codes with 8 chars' => [10, 8];
101  yield '0 codes with 8 chars' => [8, 0];
102  yield '10 codes with 10 chars' => [10, 10];
103  }
104 
109  {
110  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [
111  'className' => BcryptPasswordHash::class,
112  'options' => [
113  // Reduce default costs for quicker unit tests
114  'cost' => 10,
115  ],
116  ];
117 
118  $codes = $this->subject->generatedHashedRecoveryCodes(['12345678', '87654321']);
119 
120  self::assertTrue((new ‪BcryptPasswordHash())->isValidSaltedPW((string)$codes[0]));
121  self::assertCount(2, $codes);
122  }
123 
127  public function ‪verifyRecoveryCodeTest(): void
128  {
129  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [
130  'className' => NoopPasswordHash::class,
131  'options' => [],
132  ];
133 
134  $recoveryCode = '18742989';
135  $codes = [];
136 
137  // False on empty codes
138  self::assertFalse($this->subject->verifyRecoveryCode($recoveryCode, $codes));
139 
140  $codes = $this->subject->generatedHashedRecoveryCodes(
141  array_merge([$recoveryCode], $this->subject->generatePlainRecoveryCodes(8, 2))
142  );
143 
144  // Recovery code can be verified
145  self::assertTrue($this->subject->verifyRecoveryCode($recoveryCode, $codes));
146  // Verified code is removed from available codes
147  self::assertCount(2, $codes);
148  // Recovery code can not be verified again
149  self::assertFalse($this->subject->verifyRecoveryCode($recoveryCode, $codes));
150  }
151 
156  {
157  $code = '18742989';
158  $codes = [(new ‪NoopPasswordHash())->getHashedPassword($code)];
159 
160  // Ensure we have another default hash instance
161  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [
162  'className' => BcryptPasswordHash::class,
163  'options' => [
164  // Reduce default costs for quicker unit tests
165  'cost' => 10,
166  ],
167  ];
168 
169  self::assertTrue($this->subject->verifyRecoveryCode($code, $codes));
170  self::assertEmpty($codes);
171  }
172 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\BcryptPasswordHash
Definition: BcryptPasswordHash.php:32
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\generateRecoveryCodesTest
‪generateRecoveryCodesTest()
Definition: RecoveryCodesTest.php:48
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\setUp
‪setUp()
Definition: RecoveryCodesTest.php:30
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\tearDown
‪tearDown()
Definition: RecoveryCodesTest.php:38
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes
Definition: RecoveryCodes.php:30
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\generatePlainRecoveryCodesThrowsExceptionOnInvalidLengthTest
‪generatePlainRecoveryCodesThrowsExceptionOnInvalidLengthTest()
Definition: RecoveryCodesTest.php:72
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\Fixtures\Crypto\PasswordHashing\NoopPasswordHash\unregisterNoopPasswordHash
‪static unregisterNoopPasswordHash()
Definition: NoopPasswordHash.php:72
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\Fixtures\Crypto\PasswordHashing\NoopPasswordHash
Definition: NoopPasswordHash.php:29
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\generatePlainRecoveryCodesTest
‪generatePlainRecoveryCodesTest(int $length, int $quantity)
Definition: RecoveryCodesTest.php:86
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\verifyRecoveryCodeTest
‪verifyRecoveryCodeTest()
Definition: RecoveryCodesTest.php:127
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\Fixtures\Crypto\PasswordHashing\NoopPasswordHash\registerNoopPasswordHash
‪static registerNoopPasswordHash()
Definition: NoopPasswordHash.php:67
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\generatedHashedRecoveryCodesAreHashedWithDefaultHashInstanceTest
‪generatedHashedRecoveryCodesAreHashedWithDefaultHashInstanceTest()
Definition: RecoveryCodesTest.php:108
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\$subject
‪RecoveryCodes $subject
Definition: RecoveryCodesTest.php:28
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest
Definition: RecoveryCodesTest.php:27
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\verifyRecoveryCodeUsesTheCorrectHashInstanceTest
‪verifyRecoveryCodeUsesTheCorrectHashInstanceTest()
Definition: RecoveryCodesTest.php:155
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider\RecoveryCodesTest\generatePlainRecoveryCodesTestDataProvider
‪generatePlainRecoveryCodesTestDataProvider()
Definition: RecoveryCodesTest.php:96