aip-master-node-sumit 1.0.2 → 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 +22 -13
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,24 +1,31 @@
1
1
  const axios = require('axios');
2
- const AIP_MASTER_API = process.env.AIP_MASTER_URL || 'http://localhost:8080/api/v1';
2
+
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);
3
14
  const API_KEY = process.env.AIP_MASTER_API_KEY;
4
15
 
5
- // 🛡️ The Heartbeat System.
6
- // This continuously pings the Go Server every 5 minutes
7
- // to keep the dashboard "Live" without needing to restart the Express server!
8
16
  if (API_KEY) {
9
17
  const sendHeartbeat = async () => {
10
18
  try {
11
19
  await axios.post(`${AIP_MASTER_API}/iam/ping`, { module: 'middleware' }, {
12
20
  headers: { 'Authorization': `Bearer ${API_KEY}` },
13
- timeout: 5000 // Prevent hanging if master is slow
21
+ timeout: 5000
14
22
  });
15
23
  } catch (err) {
16
24
  // Silently fail so the client's app doesn't crash if Master API is updating
17
25
  }
18
26
  };
19
-
20
- sendHeartbeat(); // Fire immediately on server startup
21
- setInterval(sendHeartbeat, 5 * 60 * 1000); // Fire every 5 minutes forever
27
+ sendHeartbeat();
28
+ setInterval(sendHeartbeat, 5 * 60 * 1000);
22
29
  }
23
30
 
24
31
  const aipGuard = (options = { requireLogin: true }) => {
@@ -26,6 +33,7 @@ const aipGuard = (options = { requireLogin: true }) => {
26
33
 
27
34
  // LAYER 1: INFRASTRUCTURE SHIELD
28
35
  const MAX_PAYLOAD_BYTES = 2 * 1024 * 1024;
36
+
29
37
  if (req.headers['transfer-encoding'] && req.headers['transfer-encoding'].includes('chunked')) {
30
38
  return res.status(411).send("AIP Infrastructure Shield: Chunked encoding rejected.");
31
39
  }
@@ -39,7 +47,6 @@ const aipGuard = (options = { requireLogin: true }) => {
39
47
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
40
48
  res.setHeader('Access-Control-Allow-Origin', process.env.AIP_ALLOWED_ORIGIN || '*');
41
49
 
42
- // Robust Token Extraction (Checks query, cookies, and Authorization headers)
43
50
  let token = req.query.token || (req.cookies && req.cookies.aip_session);
44
51
  if (!token && req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
45
52
  token = req.headers.authorization.split(' ')[1];
@@ -50,22 +57,23 @@ const aipGuard = (options = { requireLogin: true }) => {
50
57
  // LAYER 2: IDENTITY CHECK & RBAC
51
58
  if (options.requireLogin) {
52
59
  if (!token) return res.status(401).send("Unauthorized: Missing AIP Session Token");
60
+
53
61
  try {
54
62
  const currentAction = req.method + " " + (req.baseUrl + req.path);
55
63
  const authRes = await axios.post(`${AIP_MASTER_API}/iam/verify-session`,
56
64
  { session_token: token, action: currentAction },
57
65
  { headers: { 'Authorization': `Bearer ${API_KEY}` } }
58
66
  );
67
+
59
68
  req.user = authRes.data.user;
60
69
 
61
70
  const isProd = process.env.NODE_ENV === 'production';
62
71
  res.cookie('aip_session', token, { httpOnly: true, secure: isProd });
72
+
63
73
  } catch (error) {
64
74
  const status = error.response?.status || 500;
65
75
  const errMsg = error.response?.data?.error || "AIP Identity Blocked: Invalid Token.";
66
76
 
67
- // 🛡️ CRITICAL FIX: Only clear the session cookie if the token is actually dead (401).
68
- // If it is an RBAC block (403), we just deny the action but keep them logged in!
69
77
  if (status === 401 && res.clearCookie) {
70
78
  res.clearCookie('aip_session');
71
79
  }
@@ -82,6 +90,7 @@ const aipGuard = (options = { requireLogin: true }) => {
82
90
  });
83
91
  const forwardedFor = req.headers['x-forwarded-for'];
84
92
  let clientIp = req.ip || (req.connection && req.connection.remoteAddress) || "0.0.0.0";
93
+
85
94
  if (forwardedFor) {
86
95
  clientIp = Array.isArray(forwardedFor)
87
96
  ? forwardedFor[0].trim()
@@ -96,9 +105,9 @@ const aipGuard = (options = { requireLogin: true }) => {
96
105
  payload: payloadData,
97
106
  origin: req.headers.origin || "",
98
107
  user_agent: req.headers['user-agent'] || "",
99
- session_token: token || "" // Explicitly forwarding the token to the Master WAF
108
+ session_token: token || ""
100
109
  });
101
-
110
+
102
111
  if (wafRes.data.action === "block") {
103
112
  return res.status(403).send(`AIP Firewall Blocked Request: ${wafRes.data.reason}`);
104
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aip-master-node-sumit",
3
- "version": "1.0.2",
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": {