aip-master-node-sumit 1.0.0 → 1.0.3

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.
Files changed (2) hide show
  1. package/index.js +54 -39
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,27 +1,39 @@
1
1
  const axios = require('axios');
2
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';
3
+ // 🛡️ THE FIX: Smart URL Cleaner ensures the base API URL is exactly right
4
+ const getSafeMasterUrl = (url) => {
5
+ if (!url) return 'http://localhost:8080/api/v1';
6
+ let clean = url.replace(/\/+$/, '');
7
+ if (clean.endsWith('/iam')) {
8
+ clean = clean.substring(0, clean.length - 4);
9
+ }
10
+ return clean;
11
+ };
12
+
13
+ const AIP_MASTER_API = getSafeMasterUrl(process.env.AIP_MASTER_URL);
5
14
  const API_KEY = process.env.AIP_MASTER_API_KEY;
6
15
 
7
- // Startup Ping Verification (Only runs if they provided an API key)
8
16
  if (API_KEY) {
9
- axios.post(`${AIP_MASTER_API}/iam/ping`, { module: 'middleware' }, {
10
- headers: { 'Authorization': `Bearer ${API_KEY}` }
11
- }).catch(() => {});
17
+ const sendHeartbeat = async () => {
18
+ try {
19
+ await axios.post(`${AIP_MASTER_API}/iam/ping`, { module: 'middleware' }, {
20
+ headers: { 'Authorization': `Bearer ${API_KEY}` },
21
+ timeout: 5000
22
+ });
23
+ } catch (err) {
24
+ // Silently fail so the client's app doesn't crash if Master API is updating
25
+ }
26
+ };
27
+ sendHeartbeat();
28
+ setInterval(sendHeartbeat, 5 * 60 * 1000);
12
29
  }
13
30
 
14
- /**
15
- * Universal Security Guard (God-Mode)
16
- * @param {Object} options - { requireLogin: boolean }
17
- */
18
31
  const aipGuard = (options = { requireLogin: true }) => {
19
32
  return async (req, res, next) => {
20
33
 
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
34
+ // LAYER 1: INFRASTRUCTURE SHIELD
35
+ const MAX_PAYLOAD_BYTES = 2 * 1024 * 1024;
36
+
25
37
  if (req.headers['transfer-encoding'] && req.headers['transfer-encoding'].includes('chunked')) {
26
38
  return res.status(411).send("AIP Infrastructure Shield: Chunked encoding rejected.");
27
39
  }
@@ -30,53 +42,56 @@ const aipGuard = (options = { requireLogin: true }) => {
30
42
  return res.status(413).send("AIP Infrastructure Shield: Payload Too Large.");
31
43
  }
32
44
 
33
- // Inject Secure Anti-Hacker Headers into the browser
34
45
  res.setHeader('X-Frame-Options', 'DENY');
35
46
  res.setHeader('X-Content-Type-Options', 'nosniff');
36
47
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
37
48
  res.setHeader('Access-Control-Allow-Origin', process.env.AIP_ALLOWED_ORIGIN || '*');
38
49
 
39
- // 🛡️ LAYER 2: IDENTITY CHECK & RBAC AUTO-DISCOVERY
50
+ let token = req.query.token || (req.cookies && req.cookies.aip_session);
51
+ if (!token && req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
52
+ token = req.headers.authorization.split(' ')[1];
53
+ } else if (!token && req.headers['x-aip-token']) {
54
+ token = req.headers['x-aip-token'];
55
+ }
56
+
57
+ // LAYER 2: IDENTITY CHECK & RBAC
40
58
  if (options.requireLogin) {
41
- const token = req.query.token || (req.cookies && req.cookies.aip_session);
42
- if (!token) return res.redirect('/login');
59
+ if (!token) return res.status(401).send("Unauthorized: Missing AIP Session Token");
43
60
 
44
61
  try {
45
- // The Scout: Automatically grabs the route and sends it to AIP Master for RBAC Scanning
46
62
  const currentAction = req.method + " " + (req.baseUrl + req.path);
47
63
  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
- }
64
+ { session_token: token, action: currentAction },
65
+ { headers: { 'Authorization': `Bearer ${API_KEY}` } }
55
66
  );
56
-
67
+
57
68
  req.user = authRes.data.user;
58
- res.cookie('aip_session', token, { httpOnly: true, secure: true });
69
+
70
+ const isProd = process.env.NODE_ENV === 'production';
71
+ res.cookie('aip_session', token, { httpOnly: true, secure: isProd });
59
72
 
60
73
  } catch (error) {
61
- if (res.clearCookie) res.clearCookie('aip_session');
74
+ const status = error.response?.status || 500;
62
75
  const errMsg = error.response?.data?.error || "AIP Identity Blocked: Invalid Token.";
63
- return res.status(403).send(errMsg);
76
+
77
+ if (status === 401 && res.clearCookie) {
78
+ res.clearCookie('aip_session');
79
+ }
80
+
81
+ return res.status(status === 401 ? 401 : 403).send(errMsg);
64
82
  }
65
83
  }
66
84
 
67
- // 🛡️ LAYER 3: WAF THREAT SCAN & SMART IP EXTRACTION
85
+ // LAYER 3: WAF THREAT SCAN
68
86
  try {
69
87
  const payloadData = JSON.stringify({
70
- body: req.body,
71
- query: req.query
88
+ body: req.body || {},
89
+ query: req.query || {}
72
90
  });
73
-
74
- // Smart IP Resolver: Protects clients hosted on Vercel, Heroku, or AWS
75
91
  const forwardedFor = req.headers['x-forwarded-for'];
76
92
  let clientIp = req.ip || (req.connection && req.connection.remoteAddress) || "0.0.0.0";
77
-
93
+
78
94
  if (forwardedFor) {
79
- // Handle both string and array formats safely
80
95
  clientIp = Array.isArray(forwardedFor)
81
96
  ? forwardedFor[0].trim()
82
97
  : forwardedFor.split(',')[0].trim();
@@ -89,7 +104,8 @@ const aipGuard = (options = { requireLogin: true }) => {
89
104
  url: req.originalUrl,
90
105
  payload: payloadData,
91
106
  origin: req.headers.origin || "",
92
- user_agent: req.headers['user-agent'] || ""
107
+ user_agent: req.headers['user-agent'] || "",
108
+ session_token: token || ""
93
109
  });
94
110
 
95
111
  if (wafRes.data.action === "block") {
@@ -101,7 +117,6 @@ const aipGuard = (options = { requireLogin: true }) => {
101
117
  return res.status(500).send("Security verification failed.");
102
118
  }
103
119
 
104
- // Passed all 3 Layers perfectly!
105
120
  next();
106
121
  };
107
122
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aip-master-node-sumit",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Enterprise-grade WAF and IAM security middleware for Node.js.",
5
5
  "main": "index.js",
6
6
  "scripts": {