xypriss 3.0.0 → 3.2.0
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.
- package/dist/cjs/src/middleware/XyPrissMiddlewareAPI.js +3 -2
- package/dist/cjs/src/middleware/XyPrissMiddlewareAPI.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js +88 -35
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/security/BrowserOnlyProtector.js +11 -9
- package/dist/cjs/src/middleware/built-in/security/BrowserOnlyProtector.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/security/MobileOnlyProtector.js +504 -0
- package/dist/cjs/src/middleware/built-in/security/MobileOnlyProtector.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/RequestSignatureProtector.js +465 -0
- package/dist/cjs/src/middleware/built-in/security/RequestSignatureProtector.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/TerminalOnlyProtector.js +1 -1
- package/dist/cjs/src/middleware/built-in/security/TerminalOnlyProtector.js.map +1 -1
- package/dist/cjs/src/middleware/security-middleware.js +156 -36
- package/dist/cjs/src/middleware/security-middleware.js.map +1 -1
- package/dist/cjs/src/server/const/default.js +5 -0
- package/dist/cjs/src/server/const/default.js.map +1 -1
- package/dist/esm/src/middleware/XyPrissMiddlewareAPI.js +3 -2
- package/dist/esm/src/middleware/XyPrissMiddlewareAPI.js.map +1 -1
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js +88 -35
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/esm/src/middleware/built-in/security/BrowserOnlyProtector.js +11 -9
- package/dist/esm/src/middleware/built-in/security/BrowserOnlyProtector.js.map +1 -1
- package/dist/esm/src/middleware/built-in/security/MobileOnlyProtector.js +502 -0
- package/dist/esm/src/middleware/built-in/security/MobileOnlyProtector.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/RequestSignatureProtector.js +444 -0
- package/dist/esm/src/middleware/built-in/security/RequestSignatureProtector.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/TerminalOnlyProtector.js +1 -1
- package/dist/esm/src/middleware/built-in/security/TerminalOnlyProtector.js.map +1 -1
- package/dist/esm/src/middleware/security-middleware.js +156 -36
- package/dist/esm/src/middleware/security-middleware.js.map +1 -1
- package/dist/esm/src/server/const/default.js +5 -0
- package/dist/esm/src/server/const/default.js.map +1 -1
- package/dist/index.d.ts +285 -54
- package/package.json +1 -1
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var Logger = require('../../../../shared/logger/Logger.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mobile-Only Access Protector
|
|
7
|
+
* Blocks browser requests and allows only mobile app access.
|
|
8
|
+
* Multi-layered detection with strict validation to avoid false positives.
|
|
9
|
+
*
|
|
10
|
+
* @example Enable with defaults:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* mobileOnly: true
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example Custom configuration:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* mobileOnly: {
|
|
18
|
+
* blockBrowserIndicators: true,
|
|
19
|
+
* allowedPlatforms: ['ios', 'android'],
|
|
20
|
+
* requireMobileHeaders: true,
|
|
21
|
+
* customUserAgentPatterns: [/MyApp/i],
|
|
22
|
+
* errorMessage: "Mobile app access required"
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
class MobileOnlyProtector {
|
|
27
|
+
constructor(config = {}, logger) {
|
|
28
|
+
// Mobile platform indicators
|
|
29
|
+
this.mobilePatterns = [
|
|
30
|
+
/\bAndroid\b/i,
|
|
31
|
+
/\biPhone\b/i,
|
|
32
|
+
/\biPad\b/i,
|
|
33
|
+
/\biPod\b/i,
|
|
34
|
+
/\bBlackBerry\b/i,
|
|
35
|
+
/\bWindows Phone\b/i,
|
|
36
|
+
/\bReactNative\b/i,
|
|
37
|
+
/\bExpo\b/i,
|
|
38
|
+
/\bDalvik\b/i, // Android runtime
|
|
39
|
+
];
|
|
40
|
+
// Android HTTP clients
|
|
41
|
+
this.androidHttpClients = [
|
|
42
|
+
/\bokhttp\b/i, // OkHttp
|
|
43
|
+
/\bretrofit\b/i, // Retrofit
|
|
44
|
+
/\bktor-client\b/i, // Ktor Client
|
|
45
|
+
/\bktor\b/i, // Ktor (short form)
|
|
46
|
+
/\bvolley\b/i, // Volley
|
|
47
|
+
/\bHttpUrlConnection\b/i, // HttpUrlConnection
|
|
48
|
+
/\bAndroidHttpClient\b/i, // Generic Android HTTP
|
|
49
|
+
];
|
|
50
|
+
// iOS HTTP clients
|
|
51
|
+
this.iosHttpClients = [
|
|
52
|
+
/\bAlamofire\b/i, // Alamofire
|
|
53
|
+
/\bAFNetworking\b/i, // AFNetworking
|
|
54
|
+
/\bCFNetwork\b/i, // CFNetwork (iOS networking framework)
|
|
55
|
+
/\bURLSession\b/i, // URLSession
|
|
56
|
+
/\bNSURLSession\b/i, // NSURLSession (Objective-C)
|
|
57
|
+
/\bMoya\b/i, // Moya
|
|
58
|
+
/\bSiesta\b/i, // Siesta
|
|
59
|
+
];
|
|
60
|
+
// Cross-platform mobile frameworks
|
|
61
|
+
this.mobileFameworks = [
|
|
62
|
+
/\bFlutter\b/i,
|
|
63
|
+
/\bDart\b/i, // Dart (Flutter's language)
|
|
64
|
+
/\bReact Native\b/i,
|
|
65
|
+
/\bReactNative\b/i,
|
|
66
|
+
/\bExpo\b/i,
|
|
67
|
+
/\bCapacitor\b/i, // Ionic Capacitor
|
|
68
|
+
/\bCordova\b/i, // Apache Cordova
|
|
69
|
+
/\bIonic\b/i, // Ionic Framework
|
|
70
|
+
/\bXamarin\b/i, // Xamarin
|
|
71
|
+
];
|
|
72
|
+
// Comprehensive browser indicators (aggressive detection)
|
|
73
|
+
this.browserIndicators = [
|
|
74
|
+
/\bMozilla\b/i,
|
|
75
|
+
/\bChrome\b/i,
|
|
76
|
+
/\bChromium\b/i,
|
|
77
|
+
/\bSafari\b/i,
|
|
78
|
+
/\bFirefox\b/i,
|
|
79
|
+
/\bEdge\b/i,
|
|
80
|
+
/\bEdg\b/i,
|
|
81
|
+
/\bOpera\b/i,
|
|
82
|
+
/\bOPR\b/i,
|
|
83
|
+
/\bBrave\b/i,
|
|
84
|
+
/\bVivaldi\b/i,
|
|
85
|
+
/\bSeaMonkey\b/i,
|
|
86
|
+
/\bIceweasel\b/i,
|
|
87
|
+
/\bEpiphany\b/i,
|
|
88
|
+
/\bMidori\b/i,
|
|
89
|
+
/\bKonqueror\b/i,
|
|
90
|
+
/\bWebKit\b/i,
|
|
91
|
+
/\bGecko\b/i,
|
|
92
|
+
/\bTrident\b/i,
|
|
93
|
+
/\bPresto\b/i,
|
|
94
|
+
/\bEdgeHTML\b/i,
|
|
95
|
+
/\bNetscape\b/i,
|
|
96
|
+
/\bIE\b/i,
|
|
97
|
+
/\bMSIE\b/i,
|
|
98
|
+
/\brv:11/i, // IE11
|
|
99
|
+
/\bElectron\b/i, // Desktop apps
|
|
100
|
+
/\bPhantomJS\b/i, // Headless browser
|
|
101
|
+
/\bHeadlessChrome\b/i,
|
|
102
|
+
];
|
|
103
|
+
// Known desktop OS indicators
|
|
104
|
+
this.desktopIndicators = [
|
|
105
|
+
/\bWindows NT\b/i,
|
|
106
|
+
/\bMac OS X\b/i,
|
|
107
|
+
/\bMacintosh\b/i,
|
|
108
|
+
/\bLinux x86_64\b/i,
|
|
109
|
+
/\bLinux i686\b/i,
|
|
110
|
+
/\bX11\b/i,
|
|
111
|
+
/\bWin64\b/i,
|
|
112
|
+
/\bWOW64\b/i,
|
|
113
|
+
/\bUbuntu\b/i,
|
|
114
|
+
/\bFedora\b/i,
|
|
115
|
+
/\bDebian\b/i,
|
|
116
|
+
];
|
|
117
|
+
// Suspicious patterns often used in spoofing (excluding legitimate mobile clients)
|
|
118
|
+
this.suspiciousPatterns = [
|
|
119
|
+
/\bcurl\b/i,
|
|
120
|
+
/\bwget\b/i,
|
|
121
|
+
/\bPython\b/i,
|
|
122
|
+
/\bJava(?!Script)\b/i, // Java but not JavaScript
|
|
123
|
+
/\bperl\b/i,
|
|
124
|
+
/\bruby\b/i,
|
|
125
|
+
/\bPostman\b/i,
|
|
126
|
+
/\bInsomnia\b/i,
|
|
127
|
+
/\bHTTPie\b/i,
|
|
128
|
+
/\baxios\b/i,
|
|
129
|
+
/\bnode-fetch\b/i,
|
|
130
|
+
/\bgot\b/i,
|
|
131
|
+
/\bsuperagent\b/i,
|
|
132
|
+
/\brequest\b/i,
|
|
133
|
+
/\bbot\b/i,
|
|
134
|
+
/\bcrawler\b/i,
|
|
135
|
+
/\bspider\b/i,
|
|
136
|
+
/\bscraper\b/i,
|
|
137
|
+
];
|
|
138
|
+
// Mobile-specific headers that indicate app requests
|
|
139
|
+
this.mobileHeaders = [
|
|
140
|
+
"x-requested-with",
|
|
141
|
+
"x-mobile-app",
|
|
142
|
+
"x-app-platform",
|
|
143
|
+
"x-app-version",
|
|
144
|
+
"expo-version",
|
|
145
|
+
"react-native-version",
|
|
146
|
+
"x-flutter-version",
|
|
147
|
+
"x-ios-bundle-identifier",
|
|
148
|
+
"x-android-package",
|
|
149
|
+
];
|
|
150
|
+
this.config = {
|
|
151
|
+
enable: config.enable ?? true,
|
|
152
|
+
blockBrowserIndicators: config.blockBrowserIndicators ?? true,
|
|
153
|
+
allowedPlatforms: config.allowedPlatforms ?? [
|
|
154
|
+
"ios",
|
|
155
|
+
"android",
|
|
156
|
+
"react-native",
|
|
157
|
+
"expo",
|
|
158
|
+
],
|
|
159
|
+
requireMobileHeaders: config.requireMobileHeaders ?? false,
|
|
160
|
+
customUserAgentPatterns: config.customUserAgentPatterns ?? [],
|
|
161
|
+
debug: config.debug ?? false,
|
|
162
|
+
errorMessage: config.errorMessage ??
|
|
163
|
+
"Mobile app access required. Browser requests are not allowed.",
|
|
164
|
+
statusCode: config.statusCode ?? 403,
|
|
165
|
+
caseSensitive: config.caseSensitive ?? false,
|
|
166
|
+
trimUserAgent: config.trimUserAgent ?? true,
|
|
167
|
+
};
|
|
168
|
+
this.logger =
|
|
169
|
+
logger ||
|
|
170
|
+
new Logger.Logger({
|
|
171
|
+
components: { security: true },
|
|
172
|
+
types: { debug: true },
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Normalize User-Agent string
|
|
177
|
+
*/
|
|
178
|
+
normalizeUserAgent(userAgent) {
|
|
179
|
+
if (!userAgent)
|
|
180
|
+
return "";
|
|
181
|
+
let normalized = userAgent;
|
|
182
|
+
if (this.config.trimUserAgent) {
|
|
183
|
+
normalized = normalized.trim();
|
|
184
|
+
}
|
|
185
|
+
// Remove excessive whitespace
|
|
186
|
+
normalized = normalized.replace(/\s+/g, " ");
|
|
187
|
+
return normalized;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check for Android HTTP client indicators
|
|
191
|
+
*/
|
|
192
|
+
hasAndroidHttpClient(userAgent) {
|
|
193
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
194
|
+
return this.androidHttpClients.some((pattern) => {
|
|
195
|
+
const regex = new RegExp(pattern.source, flags);
|
|
196
|
+
return regex.test(userAgent);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check for iOS HTTP client indicators
|
|
201
|
+
*/
|
|
202
|
+
hasIosHttpClient(userAgent) {
|
|
203
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
204
|
+
return this.iosHttpClients.some((pattern) => {
|
|
205
|
+
const regex = new RegExp(pattern.source, flags);
|
|
206
|
+
return regex.test(userAgent);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check for mobile framework indicators
|
|
211
|
+
*/
|
|
212
|
+
hasMobileFramework(userAgent) {
|
|
213
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
214
|
+
return this.mobileFameworks.some((pattern) => {
|
|
215
|
+
const regex = new RegExp(pattern.source, flags);
|
|
216
|
+
return regex.test(userAgent);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Check for browser indicators in User-Agent
|
|
221
|
+
*/
|
|
222
|
+
hasBrowserIndicators(userAgent) {
|
|
223
|
+
if (!this.config.blockBrowserIndicators) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
227
|
+
return this.browserIndicators.some((pattern) => {
|
|
228
|
+
const regex = new RegExp(pattern.source, flags);
|
|
229
|
+
return regex.test(userAgent);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Check for desktop OS indicators
|
|
234
|
+
*/
|
|
235
|
+
hasDesktopIndicators(userAgent) {
|
|
236
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
237
|
+
return this.desktopIndicators.some((pattern) => {
|
|
238
|
+
const regex = new RegExp(pattern.source, flags);
|
|
239
|
+
return regex.test(userAgent);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Check for suspicious patterns (bots, tools, spoofing attempts)
|
|
244
|
+
*/
|
|
245
|
+
hasSuspiciousPatterns(userAgent) {
|
|
246
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
247
|
+
return this.suspiciousPatterns.some((pattern) => {
|
|
248
|
+
const regex = new RegExp(pattern.source, flags);
|
|
249
|
+
return regex.test(userAgent);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Check if User-Agent matches custom patterns
|
|
254
|
+
*/
|
|
255
|
+
matchesCustomPatterns(userAgent) {
|
|
256
|
+
if (this.config.customUserAgentPatterns.length === 0) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
260
|
+
for (const pattern of this.config.customUserAgentPatterns) {
|
|
261
|
+
try {
|
|
262
|
+
const regex = new RegExp(pattern.source, flags);
|
|
263
|
+
if (regex.test(userAgent)) {
|
|
264
|
+
if (this.config.debug) {
|
|
265
|
+
this.logger.debug("security", `Custom pattern matched: ${pattern}`);
|
|
266
|
+
}
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
this.logger.warn("security", `Invalid custom pattern: ${pattern}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Check if User-Agent indicates allowed mobile platform
|
|
278
|
+
*/
|
|
279
|
+
hasAllowedPlatform(userAgent) {
|
|
280
|
+
return this.config.allowedPlatforms.some((platform) => {
|
|
281
|
+
switch (platform) {
|
|
282
|
+
case "ios":
|
|
283
|
+
// iOS detection: iOS devices OR iOS HTTP clients (without desktop indicators)
|
|
284
|
+
return ((/\b(iPhone|iPad|iPod)\b/i.test(userAgent) ||
|
|
285
|
+
this.hasIosHttpClient(userAgent)) &&
|
|
286
|
+
!/\b(Macintosh|Mac OS X)\b/i.test(userAgent));
|
|
287
|
+
case "android":
|
|
288
|
+
// Android detection: Android OS OR Android HTTP clients (without desktop emulator)
|
|
289
|
+
return ((/\bAndroid\b/i.test(userAgent) ||
|
|
290
|
+
/\bDalvik\b/i.test(userAgent) ||
|
|
291
|
+
this.hasAndroidHttpClient(userAgent)) &&
|
|
292
|
+
!/\b(X11|Linux x86_64)\b/i.test(userAgent));
|
|
293
|
+
case "react-native":
|
|
294
|
+
return /\b(ReactNative|React Native)\b/i.test(userAgent);
|
|
295
|
+
case "expo":
|
|
296
|
+
return /\bExpo\b/i.test(userAgent);
|
|
297
|
+
case "flutter":
|
|
298
|
+
return /\b(Flutter|Dart)\b/i.test(userAgent);
|
|
299
|
+
default:
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Check for mobile-specific patterns
|
|
306
|
+
*/
|
|
307
|
+
hasMobilePatterns(userAgent) {
|
|
308
|
+
const flags = this.config.caseSensitive ? "g" : "gi";
|
|
309
|
+
return this.mobilePatterns.some((pattern) => {
|
|
310
|
+
const regex = new RegExp(pattern.source, flags);
|
|
311
|
+
return regex.test(userAgent);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Check for mobile-specific headers
|
|
316
|
+
*/
|
|
317
|
+
hasMobileHeaders(req) {
|
|
318
|
+
if (!req.headers) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
return this.mobileHeaders.some((header) => {
|
|
322
|
+
const lowerHeader = header.toLowerCase();
|
|
323
|
+
// Check both original case and lowercase
|
|
324
|
+
return req.headers[header] || req.headers[lowerHeader];
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Validate User-Agent is not empty or suspicious
|
|
329
|
+
*/
|
|
330
|
+
isValidUserAgent(userAgent) {
|
|
331
|
+
if (!userAgent || userAgent.length === 0) {
|
|
332
|
+
if (this.config.debug) {
|
|
333
|
+
this.logger.debug("security", "Empty User-Agent detected");
|
|
334
|
+
}
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
// Allow shorter User-Agents for mobile HTTP clients (like okhttp/4.12.0)
|
|
338
|
+
if (userAgent.length < 5) {
|
|
339
|
+
if (this.config.debug) {
|
|
340
|
+
this.logger.debug("security", `Suspicious short User-Agent: ${userAgent}`);
|
|
341
|
+
}
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
// User-Agent with only generic "Mobile" is suspicious
|
|
345
|
+
if (userAgent === "Mobile" || userAgent.toLowerCase() === "mobile") {
|
|
346
|
+
if (this.config.debug) {
|
|
347
|
+
this.logger.debug("security", "Generic 'Mobile' User-Agent detected");
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Perform comprehensive mobile request validation
|
|
355
|
+
*/
|
|
356
|
+
validateMobileRequest(req, userAgent) {
|
|
357
|
+
let score = 0;
|
|
358
|
+
let reason = "";
|
|
359
|
+
const reasons = [];
|
|
360
|
+
// Phase 1: Validation checks (disqualifiers)
|
|
361
|
+
if (!this.isValidUserAgent(userAgent)) {
|
|
362
|
+
return { isValid: false, reason: "Invalid User-Agent", score: 0 };
|
|
363
|
+
}
|
|
364
|
+
if (this.hasSuspiciousPatterns(userAgent)) {
|
|
365
|
+
return {
|
|
366
|
+
isValid: false,
|
|
367
|
+
reason: "Suspicious patterns detected",
|
|
368
|
+
score: 0,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if (this.hasDesktopIndicators(userAgent)) {
|
|
372
|
+
return {
|
|
373
|
+
isValid: false,
|
|
374
|
+
reason: "Desktop OS indicators detected",
|
|
375
|
+
score: 0,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
// Check browser indicators AFTER mobile patterns to avoid false positives
|
|
379
|
+
const hasBrowser = this.hasBrowserIndicators(userAgent);
|
|
380
|
+
const hasMobilePattern = this.hasMobilePatterns(userAgent);
|
|
381
|
+
const hasAndroidClient = this.hasAndroidHttpClient(userAgent);
|
|
382
|
+
const hasIosClient = this.hasIosHttpClient(userAgent);
|
|
383
|
+
const hasMobileFramework = this.hasMobileFramework(userAgent);
|
|
384
|
+
// If blockBrowserIndicators is disabled, browsers are allowed
|
|
385
|
+
if (!this.config.blockBrowserIndicators && hasBrowser) {
|
|
386
|
+
score += 50; // Give browsers a decent score when allowed
|
|
387
|
+
reasons.push("Browser allowed (blockBrowserIndicators disabled)");
|
|
388
|
+
}
|
|
389
|
+
// If it has browser indicators but NO mobile indicators, block it (only when blocking browsers)
|
|
390
|
+
else if (hasBrowser &&
|
|
391
|
+
!hasMobilePattern &&
|
|
392
|
+
!hasAndroidClient &&
|
|
393
|
+
!hasIosClient &&
|
|
394
|
+
!hasMobileFramework) {
|
|
395
|
+
return {
|
|
396
|
+
isValid: false,
|
|
397
|
+
reason: "Browser indicators without mobile patterns",
|
|
398
|
+
score: 0,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
// Phase 2: Positive indicators (qualifiers)
|
|
402
|
+
// Custom patterns have highest priority
|
|
403
|
+
if (this.matchesCustomPatterns(userAgent)) {
|
|
404
|
+
score = 100;
|
|
405
|
+
reason = "Custom pattern match";
|
|
406
|
+
return { isValid: true, reason, score };
|
|
407
|
+
}
|
|
408
|
+
// Mobile HTTP clients (high confidence for legitimate mobile apps)
|
|
409
|
+
if (hasAndroidClient) {
|
|
410
|
+
score += 80;
|
|
411
|
+
reasons.push("Android HTTP client");
|
|
412
|
+
}
|
|
413
|
+
if (hasIosClient) {
|
|
414
|
+
score += 80;
|
|
415
|
+
reasons.push("iOS HTTP client");
|
|
416
|
+
}
|
|
417
|
+
// Mobile frameworks (high confidence)
|
|
418
|
+
if (hasMobileFramework) {
|
|
419
|
+
score += 70;
|
|
420
|
+
reasons.push("Mobile framework");
|
|
421
|
+
}
|
|
422
|
+
// Platform-specific detection (medium-high confidence)
|
|
423
|
+
if (this.hasAllowedPlatform(userAgent)) {
|
|
424
|
+
score += 60;
|
|
425
|
+
reasons.push("Allowed platform");
|
|
426
|
+
}
|
|
427
|
+
// General mobile patterns (medium confidence)
|
|
428
|
+
if (hasMobilePattern) {
|
|
429
|
+
score += 40;
|
|
430
|
+
reasons.push("Mobile patterns");
|
|
431
|
+
}
|
|
432
|
+
// Mobile headers boost confidence
|
|
433
|
+
if (this.hasMobileHeaders(req)) {
|
|
434
|
+
score += 30;
|
|
435
|
+
reasons.push("Mobile headers");
|
|
436
|
+
}
|
|
437
|
+
// Require minimum score threshold
|
|
438
|
+
const threshold = this.config.requireMobileHeaders ? 80 : 50;
|
|
439
|
+
reason =
|
|
440
|
+
reasons.length > 0 ? reasons.join(" + ") : "No mobile indicators";
|
|
441
|
+
return {
|
|
442
|
+
isValid: score >= threshold,
|
|
443
|
+
reason: score >= threshold
|
|
444
|
+
? reason
|
|
445
|
+
: `Insufficient mobile indicators (score: ${score}/${threshold})`,
|
|
446
|
+
score,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Check if request is from a mobile app
|
|
451
|
+
*/
|
|
452
|
+
isMobileRequest(req) {
|
|
453
|
+
const rawUserAgent = req.headers["user-agent"] || req.headers["User-Agent"] || "";
|
|
454
|
+
const userAgent = this.normalizeUserAgent(rawUserAgent);
|
|
455
|
+
const validation = this.validateMobileRequest(req, userAgent);
|
|
456
|
+
if (this.config.debug) {
|
|
457
|
+
this.logger.debug("security", `Validation result: ${validation.isValid ? "PASS" : "FAIL"} ` +
|
|
458
|
+
`(Score: ${validation.score}) - ${validation.reason} - UA: ${userAgent.substring(0, 100)}`);
|
|
459
|
+
}
|
|
460
|
+
return validation.isValid;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Middleware function
|
|
464
|
+
*/
|
|
465
|
+
middleware() {
|
|
466
|
+
return (req, res, next) => {
|
|
467
|
+
const userAgent = req.headers["user-agent"] ||
|
|
468
|
+
req.headers["User-Agent"] ||
|
|
469
|
+
"none";
|
|
470
|
+
if (this.config.debug) {
|
|
471
|
+
this.logger.debug("security", `MobileOnly check for ${req.ip} - UA: ${userAgent.substring(0, 100)}`);
|
|
472
|
+
}
|
|
473
|
+
if (this.isMobileRequest(req)) {
|
|
474
|
+
if (this.config.debug) {
|
|
475
|
+
this.logger.debug("security", `✅ ALLOWED mobile request from: ${req.ip}`);
|
|
476
|
+
}
|
|
477
|
+
return next();
|
|
478
|
+
}
|
|
479
|
+
this.logger.warn("security", `❌ BLOCKED non-mobile request from ${req.ip}. User-Agent: ${userAgent.substring(0, 150)}`);
|
|
480
|
+
// Check if headers already sent to prevent error
|
|
481
|
+
if (res.headersSent) {
|
|
482
|
+
this.logger.error("security", `Cannot send response for blocked request from ${req.ip} - headers already sent`);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
return res.status(this.config.statusCode).json({
|
|
486
|
+
error: "Access Denied",
|
|
487
|
+
message: this.config.errorMessage,
|
|
488
|
+
code: "MOBILE_ONLY",
|
|
489
|
+
timestamp: new Date().toISOString(),
|
|
490
|
+
userAgent: userAgent,
|
|
491
|
+
ip: req.ip,
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Get current configuration
|
|
497
|
+
*/
|
|
498
|
+
getConfig() {
|
|
499
|
+
return { ...this.config };
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
exports.MobileOnlyProtector = MobileOnlyProtector;
|
|
504
|
+
//# sourceMappingURL=MobileOnlyProtector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MobileOnlyProtector.js","sources":["../../../../../../src/middleware/built-in/security/MobileOnlyProtector.ts"],"sourcesContent":[null],"names":["Logger"],"mappings":"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"}
|