- Add TestKernel that removes the kernel.reset tag from nonceCache, rateLimitCache, sessionCache and sessionStorage pools so in-memory state survives across requests within a single test (mirroring APCu persistence in production) - Add config/packages/test/ with array cache adapters and test session config - Set fixed TOTP secret (JBSWY3DPEHPK3PXP) and high rate limits in phpunit.dist.xml and .env.test so functional tests can compute valid codes and are not rate-limited - Make Kernel non-final so TestKernel can extend it - Fix testFailedLoginWithSpentNonceIsRejected and testConsumedBackupCodeCannotBeReused: clear the CookieJar between sub-requests so a session cookie set by a prior successful login does not auto-authenticate the next request via AcceptListener before the nonce/backup-code path is exercised
42 lines
1.5 KiB
PHP
42 lines
1.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests;
|
|
|
|
use App\Kernel as AppKernel;
|
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
|
|
/**
|
|
* Kernel used by the functional test suite.
|
|
*
|
|
* In production the nonce cache is backed by APCu, which naturally persists
|
|
* across PHP requests. In the test environment the nonce cache is an
|
|
* in-memory ArrayAdapter; Symfony's ServicesResetter clears it between
|
|
* requests (even with KernelBrowser::disableReboot()), which would discard
|
|
* the nonce issued on the login-page request before the login-submission
|
|
* request can verify it.
|
|
*
|
|
* This kernel removes the kernel.reset tag from the nonceCache (and
|
|
* rateLimitCache) pools so their in-memory state survives across requests
|
|
* within a single test, mirroring the persistence behaviour of APCu.
|
|
*/
|
|
class TestKernel extends AppKernel
|
|
{
|
|
protected function build(ContainerBuilder $container): void
|
|
{
|
|
parent::build($container);
|
|
|
|
$container->addCompilerPass(new class implements CompilerPassInterface {
|
|
public function process(ContainerBuilder $container): void
|
|
{
|
|
foreach (['nonceCache', 'rateLimitCache', 'sessionCache', 'sessionStorage'] as $poolId) {
|
|
if ($container->hasDefinition($poolId)) {
|
|
$container->getDefinition($poolId)->clearTag('kernel.reset');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|