common-tg-service 1.2.28 → 1.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -23,13 +23,13 @@ const IGNORE_PATHS = [
|
|
|
23
23
|
'/',
|
|
24
24
|
'/favicon.ico',
|
|
25
25
|
'/userdata',
|
|
26
|
-
/^\/favicon
|
|
27
|
-
/^\/blockuserall
|
|
28
|
-
/^\/sendtoall
|
|
29
|
-
/^\/sendtochannel(
|
|
26
|
+
/^\/favicon(?:$|\/)/i,
|
|
27
|
+
/^\/blockuserall(?:$|\/)/i,
|
|
28
|
+
/^\/sendtoall(?:$|\/)/i,
|
|
29
|
+
/^\/sendtochannel(?:$|\/)/i,
|
|
30
30
|
'/apim',
|
|
31
31
|
'/health',
|
|
32
|
-
/^\/public(
|
|
32
|
+
/^\/public(?:$|\/)/i,
|
|
33
33
|
];
|
|
34
34
|
let AuthGuard = AuthGuard_1 = class AuthGuard {
|
|
35
35
|
constructor() {
|
|
@@ -40,8 +40,7 @@ let AuthGuard = AuthGuard_1 = class AuthGuard {
|
|
|
40
40
|
const path = request.path;
|
|
41
41
|
const url = request.url;
|
|
42
42
|
const originalUrl = request.originalUrl;
|
|
43
|
-
const apiKey = request.headers['x-api-key']?.toString() ||
|
|
44
|
-
request.query['apiKey']?.toString();
|
|
43
|
+
const apiKey = request.headers['x-api-key']?.toString() || request.query['apiKey']?.toString();
|
|
45
44
|
const clientIp = this.extractRealClientIP(request);
|
|
46
45
|
const origin = this.extractRealOrigin(request);
|
|
47
46
|
if (this.isIgnoredPath(path, url, originalUrl)) {
|
|
@@ -49,150 +48,121 @@ let AuthGuard = AuthGuard_1 = class AuthGuard {
|
|
|
49
48
|
}
|
|
50
49
|
this.logger.debug(`Request Received: ${originalUrl}`);
|
|
51
50
|
let passedReason = null;
|
|
52
|
-
if (apiKey && apiKey.toLowerCase() ===
|
|
51
|
+
if (apiKey && apiKey.toLowerCase() === 'santoor') {
|
|
53
52
|
passedReason = 'API key valid';
|
|
54
53
|
}
|
|
55
|
-
else {
|
|
56
|
-
this.logger.debug(`❌ API Key mismatch`);
|
|
57
|
-
}
|
|
58
|
-
if (!passedReason && ALLOWED_IPS.includes(clientIp)) {
|
|
54
|
+
else if (ALLOWED_IPS.includes(clientIp)) {
|
|
59
55
|
passedReason = 'IP allowed';
|
|
60
56
|
}
|
|
61
|
-
else if (
|
|
62
|
-
this.logger.debug(`❌ IP not allowed`);
|
|
63
|
-
}
|
|
64
|
-
if (!passedReason && origin && this.isOriginAllowed(origin)) {
|
|
57
|
+
else if (origin && this.isOriginAllowed(origin)) {
|
|
65
58
|
passedReason = 'Origin allowed';
|
|
66
59
|
}
|
|
67
|
-
else if (!passedReason) {
|
|
68
|
-
this.logger.debug(`❌ Origin not allowed`);
|
|
69
|
-
}
|
|
70
60
|
if (passedReason) {
|
|
71
61
|
return true;
|
|
72
62
|
}
|
|
73
63
|
this.logger.warn(`❌ Access denied — no condition satisfied`);
|
|
74
|
-
|
|
64
|
+
this.notifyUnauthorized(clientIp, origin, originalUrl);
|
|
75
65
|
throw new common_1.UnauthorizedException('Access denied: No valid API key, IP, or Origin');
|
|
76
66
|
}
|
|
77
|
-
isIgnoredPath(
|
|
78
|
-
const
|
|
79
|
-
for (const urlToTest of urlsToTest) {
|
|
67
|
+
isIgnoredPath(...urls) {
|
|
68
|
+
for (const urlToTest of urls.filter(Boolean)) {
|
|
80
69
|
for (const ignore of IGNORE_PATHS) {
|
|
81
70
|
if (typeof ignore === 'string') {
|
|
82
71
|
if (ignore.toLowerCase() === urlToTest.toLowerCase()) {
|
|
83
72
|
return true;
|
|
84
73
|
}
|
|
85
74
|
}
|
|
86
|
-
else {
|
|
87
|
-
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
75
|
+
else if (ignore.test(urlToTest)) {
|
|
76
|
+
return true;
|
|
90
77
|
}
|
|
91
78
|
}
|
|
92
79
|
}
|
|
93
80
|
return false;
|
|
94
81
|
}
|
|
95
82
|
isOriginAllowed(origin) {
|
|
96
|
-
|
|
83
|
+
try {
|
|
84
|
+
const { protocol, host } = new URL(origin.toLowerCase().trim());
|
|
85
|
+
const normalized = `${protocol}//${host}`;
|
|
86
|
+
return ALLOWED_ORIGINS.includes(normalized);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
97
89
|
return false;
|
|
98
|
-
|
|
99
|
-
return ALLOWED_ORIGINS.includes(normalizedOrigin);
|
|
90
|
+
}
|
|
100
91
|
}
|
|
101
92
|
getHeaderValue(request, headerName) {
|
|
102
93
|
return request.headers[headerName.toLowerCase()];
|
|
103
94
|
}
|
|
104
95
|
extractRealClientIP(request) {
|
|
105
96
|
const cfConnectingIP = this.getHeaderValue(request, 'cf-connecting-ip');
|
|
106
|
-
if (cfConnectingIP)
|
|
97
|
+
if (cfConnectingIP)
|
|
107
98
|
return cfConnectingIP;
|
|
108
|
-
}
|
|
109
99
|
const xRealIP = this.getHeaderValue(request, 'x-real-ip');
|
|
110
|
-
if (xRealIP)
|
|
100
|
+
if (xRealIP)
|
|
111
101
|
return xRealIP;
|
|
112
|
-
}
|
|
113
102
|
const xForwardedFor = this.getHeaderValue(request, 'x-forwarded-for');
|
|
114
|
-
if (xForwardedFor)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return cleanIP;
|
|
122
|
-
}
|
|
123
|
-
const connectionIP = request.connection?.remoteAddress;
|
|
124
|
-
if (connectionIP) {
|
|
125
|
-
const cleanIP = connectionIP.replace('::ffff:', '');
|
|
126
|
-
return cleanIP;
|
|
127
|
-
}
|
|
128
|
-
this.logger.warn(`Unable to extract client IP, using fallback`);
|
|
103
|
+
if (xForwardedFor)
|
|
104
|
+
return xForwardedFor.split(',')[0].trim();
|
|
105
|
+
if (request.ip)
|
|
106
|
+
return request.ip.replace('::ffff:', '');
|
|
107
|
+
if (request.connection?.remoteAddress)
|
|
108
|
+
return request.connection.remoteAddress.replace('::ffff:', '');
|
|
109
|
+
this.logger.warn(`Unable to extract client IP`);
|
|
129
110
|
return 'unknown';
|
|
130
111
|
}
|
|
131
112
|
extractRealOrigin(request) {
|
|
132
113
|
const origin = this.getHeaderValue(request, 'origin');
|
|
133
|
-
if (origin)
|
|
114
|
+
if (origin)
|
|
134
115
|
return origin;
|
|
135
|
-
}
|
|
136
116
|
const xOriginalHost = this.getHeaderValue(request, 'x-original-host');
|
|
137
|
-
if (xOriginalHost)
|
|
138
|
-
|
|
139
|
-
const constructedOrigin = `${protocol}://${xOriginalHost}`;
|
|
140
|
-
return constructedOrigin;
|
|
141
|
-
}
|
|
117
|
+
if (xOriginalHost)
|
|
118
|
+
return `${this.extractProtocol(request)}://${xOriginalHost}`;
|
|
142
119
|
const xForwardedHost = this.getHeaderValue(request, 'x-forwarded-host');
|
|
143
|
-
if (xForwardedHost)
|
|
144
|
-
|
|
145
|
-
const constructedOrigin = `${protocol}://${xForwardedHost}`;
|
|
146
|
-
return constructedOrigin;
|
|
147
|
-
}
|
|
120
|
+
if (xForwardedHost)
|
|
121
|
+
return `${this.extractProtocol(request)}://${xForwardedHost}`;
|
|
148
122
|
const host = this.getHeaderValue(request, 'host');
|
|
149
|
-
if (host)
|
|
150
|
-
|
|
151
|
-
const constructedOrigin = `${protocol}://${host}`;
|
|
152
|
-
return constructedOrigin;
|
|
153
|
-
}
|
|
123
|
+
if (host)
|
|
124
|
+
return `${this.extractProtocol(request)}://${host}`;
|
|
154
125
|
const referer = this.getHeaderValue(request, 'referer');
|
|
155
126
|
if (referer) {
|
|
156
127
|
try {
|
|
157
128
|
const refererUrl = new URL(referer);
|
|
158
|
-
|
|
159
|
-
return refererOrigin;
|
|
129
|
+
return `${refererUrl.protocol}//${refererUrl.host}`;
|
|
160
130
|
}
|
|
161
|
-
catch
|
|
162
|
-
this.logger.debug(`
|
|
131
|
+
catch {
|
|
132
|
+
this.logger.debug(`Invalid referer: ${referer}`);
|
|
163
133
|
}
|
|
164
134
|
}
|
|
165
|
-
this.logger.debug(`Unable to extract origin from any header`);
|
|
166
135
|
return undefined;
|
|
167
136
|
}
|
|
168
137
|
extractProtocol(request) {
|
|
169
138
|
const xForwardedProto = this.getHeaderValue(request, 'x-forwarded-proto');
|
|
170
|
-
if (xForwardedProto)
|
|
139
|
+
if (xForwardedProto)
|
|
171
140
|
return xForwardedProto.toLowerCase();
|
|
172
|
-
}
|
|
173
141
|
const cfVisitor = this.getHeaderValue(request, 'cf-visitor');
|
|
174
142
|
if (cfVisitor) {
|
|
175
143
|
try {
|
|
176
144
|
const visitor = JSON.parse(cfVisitor);
|
|
177
|
-
if (visitor.scheme)
|
|
145
|
+
if (visitor.scheme)
|
|
178
146
|
return visitor.scheme.toLowerCase();
|
|
179
|
-
}
|
|
180
147
|
}
|
|
181
|
-
catch
|
|
182
|
-
this.logger.debug(`Failed to parse CF-Visitor
|
|
148
|
+
catch {
|
|
149
|
+
this.logger.debug(`Failed to parse CF-Visitor`);
|
|
183
150
|
}
|
|
184
151
|
}
|
|
185
|
-
if (request.secure)
|
|
152
|
+
if (request.secure)
|
|
186
153
|
return 'https';
|
|
187
|
-
}
|
|
188
154
|
const xForwardedSsl = this.getHeaderValue(request, 'x-forwarded-ssl');
|
|
189
|
-
if (xForwardedSsl
|
|
155
|
+
if (xForwardedSsl?.toLowerCase() === 'on')
|
|
190
156
|
return 'https';
|
|
157
|
+
return process.env.NODE_ENV === 'production' ? 'https' : 'http';
|
|
158
|
+
}
|
|
159
|
+
notifyUnauthorized(clientIp, origin, originalUrl) {
|
|
160
|
+
try {
|
|
161
|
+
(0, utils_1.fetchWithTimeout)(`${(0, logbots_1.notifbot)()}&text=${encodeURIComponent(`${process.env.clientId || process.env.serviceName} Failed :: Unauthorized access attempt from ${clientIp || 'unknown IP'} with origin ${origin || 'unknown origin'} for ${originalUrl}`)}`);
|
|
191
162
|
}
|
|
192
|
-
|
|
193
|
-
|
|
163
|
+
catch (err) {
|
|
164
|
+
this.logger.error(`Notifbot failed: ${err.message}`);
|
|
194
165
|
}
|
|
195
|
-
return 'http';
|
|
196
166
|
}
|
|
197
167
|
};
|
|
198
168
|
exports.AuthGuard = AuthGuard;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/guards/auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA0G;AAE1G,oCAA4C;AAC5C,8CAA4C;AAE5C,MAAM,WAAW,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/guards/auth.guard.ts"],"names":[],"mappings":"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"}
|