Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
+12 -3
View File
@@ -156,7 +156,9 @@ class JwtService
// 3. Issuer (Only check if configured)
if (!empty($this->issuer) && ($decoded->iss ?? '') !== $this->issuer) {
self::abort(401, 'Invalid token issuer: expected ' . $this->issuer . ' but got ' . ($decoded->iss ?? 'none'));
// التفاصيل في اللوج فقط — لا تُكشف في الرد.
error_log('[SECURITY] Issuer mismatch | expected: ' . $this->issuer . ' | got: ' . ($decoded->iss ?? 'none'));
self::abort(401, 'Invalid token issuer');
}
// 3.1 App Signature Verification (Service Only)
@@ -228,8 +230,15 @@ class JwtService
}
if ($fpInToken === null || $fpHeader === null) {
$allHeaders = json_encode(getallheaders());
error_log("[SECURITY] Fingerprint missing | user: $userId | fpInToken: " . ($fpInToken ?? 'NULL') . " | fpHeader: " . ($fpHeader ?? 'NULL') . " | Headers: $allHeaders");
// ملاحظة: ممنوع تسجيل الهيدرز كاملة — كانت تُسرّب الـ
// Authorization: Bearer <token> بالنص الصريح إلى error_log.
// نسجّل فقط أيّ الطرفين ناقص، دون أي قيمة.
error_log(sprintf(
"[SECURITY] Fingerprint missing | user: %s | inToken: %s | inHeader: %s",
$userId,
$fpInToken === null ? 'no' : 'yes',
$fpHeader === null ? 'no' : 'yes'
));
self::abort(403, 'Device verification required');
}
+10 -2
View File
@@ -11,7 +11,7 @@ class RateLimiter
// حدود مختلفة لكل نوع endpoint
private const LIMITS = [
'login' => ['requests' => 5, 'window' => 60], // 5 محاولات / دقيقة
'tester_login' => ['requests' => 3, 'window' => 60], // 3 محاولات / دقيقة
'tester_login' => ['requests' => 30, 'window' => 60], // 30 محاولة / دقيقة (مراجعو المتاجر يكرّرون الدخول بسرعة)
'otp' => ['requests' => 3, 'window' => 300], // 3 محاولات / 5 دقائق
'register' => ['requests' => 3, 'window' => 3600], // 3 محاولات / ساعة
'api' => ['requests' => 180, 'window' => 60], // 180 طلب / دقيقة (الإنتاج الرسمى)
@@ -79,7 +79,15 @@ class RateLimiter
// ── بناء معرّف المستخدم ────────────────────────────────────
public static function identifier(?string $userId = null): string
{
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
// كان REMOTE_ADDR وحده، وهو خلف دوكر دائماً عنوان الوسيط نفسه
// (172.24.0.1) — فيتشارك كل المستخدمين دلواً واحداً، ومحاولات دخول
// فاشلة من عميل واحد تحجب الجميع بـ 429 (ظهر ذلك في سجل الإنتاج).
// clientIp() تستخرج العميل الحقيقي من X-Forwarded-For ولا تثق به
// إلا إذا كان REMOTE_ADDR وسيطاً موثوقاً.
$ip = function_exists('clientIp')
? clientIp()
: ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
return $userId ? "{$ip}:{$userId}" : $ip;
}