Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
233
tests/Framework/Security/AuthenticationSecurityTest.php
Normal file
233
tests/Framework/Security/AuthenticationSecurityTest.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Framework\Security;
|
||||
|
||||
use App\Framework\Auth\Auth;
|
||||
use App\Framework\Http\MiddlewareContext;
|
||||
use App\Framework\Http\Middlewares\AuthMiddleware;
|
||||
use App\Framework\Http\Next;
|
||||
use App\Framework\Http\Request;
|
||||
use App\Framework\Http\RequestStateManager;
|
||||
use App\Framework\Http\Session\SessionInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Critical Security Tests for Authentication
|
||||
* Tests gegen OWASP A07:2021 – Identification and Authentication Failures
|
||||
*/
|
||||
final class AuthenticationSecurityTest extends TestCase
|
||||
{
|
||||
private SessionInterface $session;
|
||||
|
||||
private Auth $auth;
|
||||
|
||||
private AuthMiddleware $middleware;
|
||||
|
||||
private RequestStateManager $stateManager;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->session = $this->createMock(SessionInterface::class);
|
||||
$this->auth = $this->createMock(Auth::class);
|
||||
$this->middleware = new AuthMiddleware($this->auth);
|
||||
$this->stateManager = $this->createMock(RequestStateManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Nicht-authentifizierte Benutzer werden blockiert
|
||||
* OWASP A07:2021 – Identification and Authentication Failures
|
||||
*/
|
||||
public function test_blocks_unauthenticated_access(): void
|
||||
{
|
||||
// Arrange: Benutzer nicht authentifiziert
|
||||
$this->auth->method('isAuthenticated')->willReturn(false);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
$next->expects($this->never())->method('__invoke');
|
||||
|
||||
// Act & Assert: Exception erwartet
|
||||
$this->expectException(\App\Framework\Http\Exception\HttpException::class);
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Authentifizierte Benutzer werden durchgelassen
|
||||
*/
|
||||
public function test_allows_authenticated_access(): void
|
||||
{
|
||||
// Arrange: Benutzer authentifiziert
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
$next->expects($this->once())->method('__invoke')->willReturn($context);
|
||||
|
||||
// Act
|
||||
$result = $this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
|
||||
// Assert
|
||||
$this->assertSame($context, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Session Hijacking Schutz
|
||||
* Validiert Session-Fingerprinting
|
||||
*/
|
||||
public function test_session_fingerprint_validation(): void
|
||||
{
|
||||
// Arrange: Authentifiziert aber Session-Fingerprint geändert
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
$this->auth->method('validateSessionFingerprint')->willReturn(false);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: Session Hijacking erkannt
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Session fingerprint validation failed');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Concurrent Login Detection
|
||||
* Erkennt verdächtige gleichzeitige Logins
|
||||
*/
|
||||
public function test_concurrent_login_detection(): void
|
||||
{
|
||||
// Arrange: Benutzer von verschiedenen IPs eingeloggt
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
$this->auth->method('validateSessionFingerprint')->willReturn(true);
|
||||
$this->auth->method('detectConcurrentSessions')->willReturn(true);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: Concurrent Session erkannt
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Concurrent session detected');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Session Timeout Validierung
|
||||
*/
|
||||
public function test_session_timeout_validation(): void
|
||||
{
|
||||
// Arrange: Session abgelaufen
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
$this->auth->method('isSessionExpired')->willReturn(true);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: Session Timeout
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Session expired');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Rate Limiting für Authentication Failures
|
||||
* Verhindert Brute Force Attacks
|
||||
*/
|
||||
public function test_authentication_rate_limiting(): void
|
||||
{
|
||||
// Arrange: Zu viele fehlgeschlagene Login-Versuche
|
||||
$this->auth->method('isAuthenticated')->willReturn(false);
|
||||
$this->auth->method('isRateLimited')->willReturn(true);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: Rate Limit erreicht
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Authentication rate limit exceeded');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: IP Whitelist Validation
|
||||
* Admin-Bereiche nur von bestimmten IPs
|
||||
*/
|
||||
public function test_ip_whitelist_validation(): void
|
||||
{
|
||||
// Arrange: IP nicht in Whitelist
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
$this->auth->method('isIpWhitelisted')->willReturn(false);
|
||||
|
||||
$request = $this->createRequestWithIp('192.168.1.100');
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: IP nicht erlaubt
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Access from this IP address is not allowed');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Account Lockout nach fehlgeschlagenen Versuchen
|
||||
*/
|
||||
public function test_account_lockout_after_failed_attempts(): void
|
||||
{
|
||||
// Arrange: Account gesperrt nach zu vielen Versuchen
|
||||
$this->auth->method('isAuthenticated')->willReturn(false);
|
||||
$this->auth->method('isAccountLocked')->willReturn(true);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: Account gesperrt
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Account is locked due to too many failed attempts');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: Two-Factor Authentication Validation
|
||||
*/
|
||||
public function test_two_factor_authentication_required(): void
|
||||
{
|
||||
// Arrange: 2FA erforderlich aber nicht bereitgestellt
|
||||
$this->auth->method('isAuthenticated')->willReturn(true);
|
||||
$this->auth->method('requires2FA')->willReturn(true);
|
||||
$this->auth->method('is2FAValid')->willReturn(false);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$context = new MiddlewareContext($request);
|
||||
$next = $this->createMock(Next::class);
|
||||
|
||||
// Act & Assert: 2FA erforderlich
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('Two-factor authentication required');
|
||||
|
||||
$this->middleware->__invoke($context, $next, $this->stateManager);
|
||||
}
|
||||
|
||||
// Helper Methods
|
||||
|
||||
private function createRequestWithIp(string $ip): Request
|
||||
{
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getClientIp')->willReturn($ip);
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user