harden(rate-limiter): fail secure login scopes with cache fallback
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace MintyPHP\Tests\Service\Security;
|
||||
|
||||
use MintyPHP\Repository\Security\RateLimitRepositoryInterface;
|
||||
use MintyPHP\Service\Security\RateLimiterFallbackGateway;
|
||||
use MintyPHP\Service\Security\RateLimiterService;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -284,6 +285,53 @@ class RateLimiterServiceTest extends TestCase
|
||||
$this->assertSame(0, $result['retry_after']);
|
||||
}
|
||||
|
||||
public function testIsBlockedFailsSecureOnExceptionForLoginAuthScope(): void
|
||||
{
|
||||
$this->repository->method('findByScopeAndHash')
|
||||
->willThrowException(new \RuntimeException('DB down'));
|
||||
|
||||
$result = $this->service->isBlocked('api.auth.login.ip', '127.0.0.1');
|
||||
|
||||
$this->assertFalse($result['allowed']);
|
||||
$this->assertSame(30, $result['retry_after']);
|
||||
}
|
||||
|
||||
public function testRegisterFailureFailsSecureOnExceptionForLoginAuthScope(): void
|
||||
{
|
||||
$this->repository->method('findByScopeAndHash')
|
||||
->willThrowException(new \RuntimeException('DB down'));
|
||||
|
||||
$result = $this->service->registerFailure('login.password.email_ip', 'user@example.com|127.0.0.1', 5, 900, 900);
|
||||
|
||||
$this->assertFalse($result['allowed']);
|
||||
$this->assertSame(30, $result['retry_after']);
|
||||
}
|
||||
|
||||
public function testIsBlockedUsesFallbackGatewayWhenStorageFails(): void
|
||||
{
|
||||
$subject = '127.0.0.1';
|
||||
$subjectHash = hash('sha256', $subject);
|
||||
$fallback = $this->createMock(RateLimiterFallbackGateway::class);
|
||||
|
||||
$fallback->expects($this->once())
|
||||
->method('load')
|
||||
->with('api.auth.login.ip', $subjectHash)
|
||||
->willReturn([
|
||||
'hits' => 7,
|
||||
'window_started_at' => time(),
|
||||
'blocked_until' => time() + 120,
|
||||
]);
|
||||
|
||||
$this->repository->method('findByScopeAndHash')
|
||||
->willThrowException(new \RuntimeException('DB down'));
|
||||
|
||||
$service = new RateLimiterService($this->repository, $fallback);
|
||||
$result = $service->isBlocked('api.auth.login.ip', $subject);
|
||||
|
||||
$this->assertFalse($result['allowed']);
|
||||
$this->assertGreaterThan(0, $result['retry_after']);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// reset
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user