aip-master-node-sumit 1.0.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/index.js +109 -0
- package/package.json +20 -0
package/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
// 🛡️ THE FIX: Allow clients to define the URL, or default to your live production API
|
|
4
|
+
const AIP_MASTER_API = process.env.AIP_MASTER_URL || 'http://localhost:8080/api/v1';
|
|
5
|
+
const API_KEY = process.env.AIP_MASTER_API_KEY;
|
|
6
|
+
|
|
7
|
+
// Startup Ping Verification (Only runs if they provided an API key)
|
|
8
|
+
if (API_KEY) {
|
|
9
|
+
axios.post(`${AIP_MASTER_API}/iam/ping`, { module: 'middleware' }, {
|
|
10
|
+
headers: { 'Authorization': `Bearer ${API_KEY}` }
|
|
11
|
+
}).catch(() => {});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Universal Security Guard (God-Mode)
|
|
16
|
+
* @param {Object} options - { requireLogin: boolean }
|
|
17
|
+
*/
|
|
18
|
+
const aipGuard = (options = { requireLogin: true }) => {
|
|
19
|
+
return async (req, res, next) => {
|
|
20
|
+
|
|
21
|
+
// 🛡️ LAYER 1: INFRASTRUCTURE SHIELD (Anti-DDoS & Header Hacks)
|
|
22
|
+
const MAX_PAYLOAD_BYTES = 2 * 1024 * 1024; // 2MB Upload Limit
|
|
23
|
+
|
|
24
|
+
// Block advanced Chunked Encoding bypass attacks
|
|
25
|
+
if (req.headers['transfer-encoding'] && req.headers['transfer-encoding'].includes('chunked')) {
|
|
26
|
+
return res.status(411).send("AIP Infrastructure Shield: Chunked encoding rejected.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (req.headers['content-length'] && parseInt(req.headers['content-length']) > MAX_PAYLOAD_BYTES) {
|
|
30
|
+
return res.status(413).send("AIP Infrastructure Shield: Payload Too Large.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Inject Secure Anti-Hacker Headers into the browser
|
|
34
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
35
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
36
|
+
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
|
37
|
+
res.setHeader('Access-Control-Allow-Origin', process.env.AIP_ALLOWED_ORIGIN || '*');
|
|
38
|
+
|
|
39
|
+
// 🛡️ LAYER 2: IDENTITY CHECK & RBAC AUTO-DISCOVERY
|
|
40
|
+
if (options.requireLogin) {
|
|
41
|
+
const token = req.query.token || (req.cookies && req.cookies.aip_session);
|
|
42
|
+
if (!token) return res.redirect('/login');
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
// The Scout: Automatically grabs the route and sends it to AIP Master for RBAC Scanning
|
|
46
|
+
const currentAction = req.method + " " + (req.baseUrl + req.path);
|
|
47
|
+
const authRes = await axios.post(`${AIP_MASTER_API}/iam/verify-session`,
|
|
48
|
+
{
|
|
49
|
+
session_token: token,
|
|
50
|
+
action: currentAction
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
headers: { 'Authorization': `Bearer ${API_KEY}` }
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
req.user = authRes.data.user;
|
|
58
|
+
res.cookie('aip_session', token, { httpOnly: true, secure: true });
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (res.clearCookie) res.clearCookie('aip_session');
|
|
62
|
+
const errMsg = error.response?.data?.error || "AIP Identity Blocked: Invalid Token.";
|
|
63
|
+
return res.status(403).send(errMsg);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 🛡️ LAYER 3: WAF THREAT SCAN & SMART IP EXTRACTION
|
|
68
|
+
try {
|
|
69
|
+
const payloadData = JSON.stringify({
|
|
70
|
+
body: req.body,
|
|
71
|
+
query: req.query
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Smart IP Resolver: Protects clients hosted on Vercel, Heroku, or AWS
|
|
75
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
76
|
+
let clientIp = req.ip || (req.connection && req.connection.remoteAddress) || "0.0.0.0";
|
|
77
|
+
|
|
78
|
+
if (forwardedFor) {
|
|
79
|
+
// Handle both string and array formats safely
|
|
80
|
+
clientIp = Array.isArray(forwardedFor)
|
|
81
|
+
? forwardedFor[0].trim()
|
|
82
|
+
: forwardedFor.split(',')[0].trim();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const wafRes = await axios.post(`${AIP_MASTER_API}/verify`, {
|
|
86
|
+
api_key: API_KEY,
|
|
87
|
+
ip: clientIp,
|
|
88
|
+
method: req.method,
|
|
89
|
+
url: req.originalUrl,
|
|
90
|
+
payload: payloadData,
|
|
91
|
+
origin: req.headers.origin || "",
|
|
92
|
+
user_agent: req.headers['user-agent'] || ""
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (wafRes.data.action === "block") {
|
|
96
|
+
return res.status(403).send(`AIP Firewall Blocked Request: ${wafRes.data.reason}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error("WAF Engine Unreachable");
|
|
101
|
+
return res.status(500).send("Security verification failed.");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Passed all 3 Layers perfectly!
|
|
105
|
+
next();
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
module.exports = aipGuard;
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aip-master-node-sumit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Enterprise-grade WAF and IAM security middleware for Node.js.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"security",
|
|
11
|
+
"waf",
|
|
12
|
+
"iam",
|
|
13
|
+
"hospital-management"
|
|
14
|
+
],
|
|
15
|
+
"author": "Sumit Rajwani",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"axios": "^1.13.6"
|
|
19
|
+
}
|
|
20
|
+
}
|