feat: Enhance WebSocket authentication and connection handling

- Add robust authentication mechanism for WebSocket connections
- Implement API key validation for both instance-specific and global tokens
- Improve connection request handling with detailed logging
- Refactor WebSocket controller to support more secure connection validation
This commit is contained in:
Davidson Gomes 2025-03-06 09:17:43 -03:00
parent 2198a86ae4
commit 32cde710b8
2 changed files with 956 additions and 862 deletions

1770
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import { PrismaRepository } from '@api/repository/repository.service';
import { WAMonitoringService } from '@api/services/monitor.service';
import { configService, Cors, Log, Websocket } from '@config/env.config';
import { Auth, configService, Cors, Log, Websocket } from '@config/env.config';
import { Logger } from '@config/logger.config';
import { Server } from 'http';
import { Server as SocketIO } from 'socket.io';
@ -24,8 +24,40 @@ export class WebsocketController extends EventController implements EventControl
}
this.socket = new SocketIO(httpServer, {
cors: {
origin: this.cors,
cors: { origin: this.cors },
allowRequest: async (req, callback) => {
try {
const url = new URL(req.url || '', 'http://localhost');
const params = new URLSearchParams(url.search);
// Permite conexões internas do Socket.IO (EIO=4 é o Engine.IO v4)
if (params.has('EIO')) {
return callback(null, true);
}
const apiKey = params.get('apikey') || (req.headers.apikey as string);
if (!apiKey) {
this.logger.error('Connection rejected: apiKey not provided');
return callback('apiKey is required', false);
}
const instance = await this.prismaRepository.instance.findFirst({ where: { token: apiKey } });
if (!instance) {
const globalToken = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
if (apiKey !== globalToken) {
this.logger.error('Connection rejected: invalid global token');
return callback('Invalid global token', false);
}
}
callback(null, true);
} catch (error) {
this.logger.error('Authentication error:');
this.logger.error(error);
callback('Authentication error', false);
}
},
});
@ -101,10 +133,7 @@ export class WebsocketController extends EventController implements EventControl
this.socket.emit(event, message);
if (logEnabled) {
this.logger.log({
local: `${origin}.sendData-WebsocketGlobal`,
...message,
});
this.logger.log({ local: `${origin}.sendData-WebsocketGlobal`, ...message });
}
}
@ -119,10 +148,7 @@ export class WebsocketController extends EventController implements EventControl
this.socket.of(`/${instanceName}`).emit(event, message);
if (logEnabled) {
this.logger.log({
local: `${origin}.sendData-Websocket`,
...message,
});
this.logger.log({ local: `${origin}.sendData-Websocket`, ...message });
}
}
} catch (err) {