Skip to content

Commit 659a140

Browse files
matheusmartinsInspermatheusmartinsInsper
authored andcommitted
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
1 parent bf1e936 commit 659a140

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

src/api/integrations/event/websocket/websocket.controller.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PrismaRepository } from '@api/repository/repository.service';
22
import { WAMonitoringService } from '@api/services/monitor.service';
3-
import { configService, Cors, Log, Websocket } from '@config/env.config';
3+
import { Auth, configService, Cors, Log, Websocket } from '@config/env.config';
44
import { Logger } from '@config/logger.config';
55
import { Server } from 'http';
66
import { Server as SocketIO } from 'socket.io';
@@ -24,8 +24,40 @@ export class WebsocketController extends EventController implements EventControl
2424
}
2525

2626
this.socket = new SocketIO(httpServer, {
27-
cors: {
28-
origin: this.cors,
27+
cors: { origin: this.cors },
28+
allowRequest: async (req, callback) => {
29+
try {
30+
const url = new URL(req.url || '', 'http://localhost');
31+
const params = new URLSearchParams(url.search);
32+
33+
// Permite conexões internas do Socket.IO (EIO=4 é o Engine.IO v4)
34+
if (params.has('EIO')) {
35+
return callback(null, true);
36+
}
37+
38+
const apiKey = params.get('apikey') || (req.headers.apikey as string);
39+
40+
if (!apiKey) {
41+
this.logger.error('Connection rejected: apiKey not provided');
42+
return callback('apiKey is required', false);
43+
}
44+
45+
const instance = await this.prismaRepository.instance.findFirst({ where: { token: apiKey } });
46+
47+
if (!instance) {
48+
const globalToken = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
49+
if (apiKey !== globalToken) {
50+
this.logger.error('Connection rejected: invalid global token');
51+
return callback('Invalid global token', false);
52+
}
53+
}
54+
55+
callback(null, true);
56+
} catch (error) {
57+
this.logger.error('Authentication error:');
58+
this.logger.error(error);
59+
callback('Authentication error', false);
60+
}
2961
},
3062
});
3163

@@ -101,10 +133,7 @@ export class WebsocketController extends EventController implements EventControl
101133
this.socket.emit(event, message);
102134

103135
if (logEnabled) {
104-
this.logger.log({
105-
local: `${origin}.sendData-WebsocketGlobal`,
106-
...message,
107-
});
136+
this.logger.log({ local: `${origin}.sendData-WebsocketGlobal`, ...message });
108137
}
109138
}
110139

@@ -119,10 +148,7 @@ export class WebsocketController extends EventController implements EventControl
119148
this.socket.of(`/${instanceName}`).emit(event, message);
120149

121150
if (logEnabled) {
122-
this.logger.log({
123-
local: `${origin}.sendData-Websocket`,
124-
...message,
125-
});
151+
this.logger.log({ local: `${origin}.sendData-Websocket`, ...message });
126152
}
127153
}
128154
} catch (err) {

0 commit comments

Comments
 (0)