getHeader('X-Api-Key'); $signature = $request->getHeader('X-Signature'); $timestamp = $request->getHeader('X-Timestamp'); $nonce = $request->getHeader('X-Nonce'); if (!$publicKey || !$signature || !$timestamp || !$nonce) { Response::error('بيانات التوقيع (HMAC) ناقصة', 'HMAC_MISSING', 401); return null; } // 1. Lookup Secret by Public Key $db = Database::getInstance(); $stmt = $db->prepare("SELECT secret_hash, tenant_id FROM api_keys WHERE public_key = ? AND is_active = 1 LIMIT 1"); $stmt->execute([$publicKey]); $apiKey = $stmt->fetch(); if (!$apiKey) { Response::error('مفتاح API غير صالح', 'HMAC_INVALID_KEY', 401); return null; } // 2. Verify Signature // Note: secret_hash in DB is the actual secret for signing $isValid = $this->hmac->verify( $apiKey['secret_hash'], $request->getMethod(), $request->getPath(), $timestamp, $nonce, json_encode($request->getBody()), $signature ); if (!$isValid) { Response::error('توقيع الطلب غير صحيح', 'HMAC_INVALID_SIGNATURE', 401); return null; } // 3. Set context $request->tenantId = $apiKey['tenant_id']; return $next($request); } }