feat: enhance CORS configuration for development and production environments

- Updated backend CORS setup to differentiate between development (open origins) and production (restricted origins).
- Implemented support for additional allowed origins via environment variables.
- Adjusted `WebSocketGateway` CORS settings to align with the new configuration.
- Updated `PROJECT_STATUS.md` to reflect progress on CORS-related security tasks.
This commit is contained in:
2025-05-16 18:10:42 +02:00
parent 3dcd57633d
commit b3a95378f1
3 changed files with 49 additions and 15 deletions

View File

@@ -16,12 +16,41 @@ async function bootstrap() {
}),
);
// Configuration CORS
app.enableCors({
origin: configService.get<string>('CORS_ORIGIN', 'http://localhost:3000'),
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
});
// Configuration CORS selon l'environnement
const environment = configService.get<string>('NODE_ENV', 'development');
const frontendUrl = configService.get<string>('FRONTEND_URL', 'http://localhost:3001');
if (environment === 'development') {
// En développement, on autorise toutes les origines avec credentials
app.enableCors({
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});
console.log('CORS configured for development environment (all origins allowed)');
} else {
// En production, on restreint les origines autorisées
const allowedOrigins = [frontendUrl];
// Ajouter d'autres origines si nécessaire (ex: sous-domaines, CDN, etc.)
if (configService.get<string>('ADDITIONAL_CORS_ORIGINS')) {
allowedOrigins.push(...configService.get<string>('ADDITIONAL_CORS_ORIGINS').split(','));
}
app.enableCors({
origin: (origin, callback) => {
// Permettre les requêtes sans origine (comme les appels d'API mobile)
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error(`Origin ${origin} not allowed by CORS`));
}
},
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
maxAge: 86400, // 24 heures de mise en cache des résultats preflight
});
console.log(`CORS configured for production environment with allowed origins: ${allowedOrigins.join(', ')}`);
}
// Préfixe global pour les routes API
app.setGlobalPrefix(configService.get<string>('API_PREFIX', 'api'));

View File

@@ -24,15 +24,20 @@ import { Server, Socket } from 'socket.io';
*/
@WebSocketGateway({
cors: {
origin: process.env.FRONTEND_URL || 'http://localhost:3001',
origin: process.env.NODE_ENV === 'development'
? true
: [
process.env.FRONTEND_URL || 'http://localhost:3001',
...(process.env.ADDITIONAL_CORS_ORIGINS ? process.env.ADDITIONAL_CORS_ORIGINS.split(',') : [])
],
credentials: true,
},
})
export class WebSocketsGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer() server: Server;
private logger = new Logger('WebSocketsGateway');
private connectedClients = new Map<string, string>(); // socketId -> userId
@@ -48,7 +53,7 @@ export class WebSocketsGateway
*/
handleConnection(client: Socket, ...args: any[]) {
const userId = client.handshake.query.userId as string;
if (userId) {
this.connectedClients.set(client.id, userId);
client.join(`user:${userId}`);
@@ -149,4 +154,4 @@ export class WebSocketsGateway
this.server.to(`project:${projectId}`).emit('notification:new', data);
this.logger.log(`Emitted notification:new for project ${projectId}`);
}
}
}