feat: enhance security configuration and SSE management with robust token validation and client tracking

- Refactored `.env.example` with comprehensive security and configuration parameters
- Added new `security.config.ts` for centralized security configuration management
- Improved middleware with enhanced authentication, request validation, and error handling
- Updated SSE routes and manager with advanced client tracking, rate limiting, and connection management
- Implemented more granular token validation with IP-based rate limiting and connection tracking
- Added detailed error responses and improved logging for security-related events
This commit is contained in:
jango-blockchained
2025-02-03 22:02:12 +01:00
parent 840927998e
commit a814c427e9
8 changed files with 605 additions and 227 deletions

View File

@@ -2,28 +2,35 @@ import { Router } from 'express';
import { v4 as uuidv4 } from 'uuid';
import { sseManager } from '../sse/index.js';
import { TokenManager } from '../security/index.js';
import { middleware } from '../middleware/index.js';
const router = Router();
// SSE endpoints
router.get('/subscribe', (req, res) => {
router.get('/subscribe_events', middleware.wsRateLimiter, (req, res) => {
try {
// Get token from query parameter
const token = req.query.token?.toString();
// Get token from query parameter and validate
const token = req.query.token?.toString() || '';
const clientIp = req.ip || req.socket.remoteAddress || '';
const validationResult = TokenManager.validateToken(token, clientIp);
if (!token || !TokenManager.validateToken(token)) {
if (!validationResult.valid) {
return res.status(401).json({
success: false,
message: 'Unauthorized - Invalid token'
message: 'Unauthorized',
error: validationResult.error,
timestamp: new Date().toISOString()
});
}
// Set SSE headers
// Set SSE headers with enhanced security
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Cache-Control': 'no-cache, no-transform',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
'X-Accel-Buffering': 'no',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'
});
// Send initial connection message
@@ -36,49 +43,51 @@ router.get('/subscribe', (req, res) => {
const clientId = uuidv4();
const client = {
id: clientId,
ip: clientIp,
connectedAt: new Date(),
send: (data: string) => {
res.write(`data: ${data}\n\n`);
}
};
// Add client to SSE manager
// Add client to SSE manager with enhanced tracking
const sseClient = sseManager.addClient(client, token);
if (!sseClient || !sseClient.authenticated) {
res.write(`data: ${JSON.stringify({
const errorMessage = JSON.stringify({
type: 'error',
message: sseClient ? 'Authentication failed' : 'Maximum client limit reached',
timestamp: new Date().toISOString()
})}\n\n`);
});
res.write(`data: ${errorMessage}\n\n`);
return res.end();
}
// Subscribe to events if specified
const events = req.query.events?.toString().split(',').filter(Boolean);
if (events?.length) {
events.forEach(event => sseManager.subscribeToEvent(clientId, event));
}
// Subscribe to entity if specified
const entityId = req.query.entity_id?.toString();
if (entityId) {
sseManager.subscribeToEntity(clientId, entityId);
}
// Subscribe to domain if specified
const domain = req.query.domain?.toString();
if (domain) {
sseManager.subscribeToDomain(clientId, domain);
}
// Handle client disconnect
req.on('close', () => {
sseManager.removeClient(clientId);
console.log(`Client ${clientId} disconnected at ${new Date().toISOString()}`);
});
// Handle errors
req.on('error', (error) => {
console.error(`SSE Error for client ${clientId}:`, error);
const errorMessage = JSON.stringify({
type: 'error',
message: 'Connection error',
timestamp: new Date().toISOString()
});
res.write(`data: ${errorMessage}\n\n`);
sseManager.removeClient(clientId);
res.end();
});
} catch (error) {
console.error('SSE Setup Error:', error);
res.status(500).json({
success: false,
message: error instanceof Error ? error.message : 'Unknown error occurred'
message: 'Internal Server Error',
error: error instanceof Error ? error.message : 'An unexpected error occurred',
timestamp: new Date().toISOString()
});
}
});
@@ -96,4 +105,4 @@ router.get('/stats', async (req, res) => {
}
});
export { router as sseRoutes };
export default router;