soajs.controller 4.2.42 → 4.3.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/.github/workflows/ci.yml +43 -0
- package/.github/workflows/release.yml +94 -0
- package/ARCHITECTURE.md +193 -0
- package/Gruntfile.js +1 -1
- package/docs/configuration-custom-registry.md +421 -0
- package/docs/configuration-services-config.md +275 -0
- package/docs/data-flow.md +138 -0
- package/docs/deployment.md +205 -0
- package/docs/external-integrations.md +159 -0
- package/docs/gateway-routes.md +259 -0
- package/docs/maintenance-routes.md +308 -0
- package/docs/middleware/awareness.md +120 -0
- package/docs/middleware/cors.md +88 -0
- package/docs/middleware/enhancer.md +75 -0
- package/docs/middleware/favicon.md +36 -0
- package/docs/middleware/gotoService.md +146 -0
- package/docs/middleware/ip2ban.md +70 -0
- package/docs/middleware/key.md +196 -0
- package/docs/middleware/keyACL.md +139 -0
- package/docs/middleware/lastSeen.md +111 -0
- package/docs/middleware/maintenanceMode.md +81 -0
- package/docs/middleware/mt.md +568 -0
- package/docs/middleware/oauth.md +173 -0
- package/docs/middleware/response.md +106 -0
- package/docs/middleware/soajs.md +71 -0
- package/docs/middleware/traffic.md +190 -0
- package/docs/middleware/url.md +102 -0
- package/docs/multi-tenant-security.md +183 -0
- package/docs/request-flow.md +230 -0
- package/docs/service-discovery.md +167 -0
- package/mw/key/index.js +16 -1
- package/mw/mt/urac.js +21 -1
- package/mw/mt/utils.js +2 -0
- package/package.json +13 -13
- package/test/unit/mw/key/index.js +150 -0
- package/test/unit/mw/mt/urac.js +157 -4
- package/.travis.yml +0 -72
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# Custom Registry Configuration
|
|
2
|
+
|
|
3
|
+
Environment-specific gateway settings stored in the Core DB custom registry.
|
|
4
|
+
|
|
5
|
+
## Configuration Structure Overview
|
|
6
|
+
|
|
7
|
+
These settings are accessed via `registry.custom.gateway.value.*` and `registry.custom.oauth.value.*`.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
registry.custom
|
|
11
|
+
├── gateway
|
|
12
|
+
│ └── value
|
|
13
|
+
│ ├── mt
|
|
14
|
+
│ │ └── whitelist # IP whitelist for bypassing security
|
|
15
|
+
│ ├── traffic
|
|
16
|
+
│ │ ├── model # Throttling storage backend
|
|
17
|
+
│ │ ├── ip2ban # Banned IP addresses
|
|
18
|
+
│ │ └── throttling # Service-level rate limiting
|
|
19
|
+
│ ├── maintenanceMode # Gateway maintenance mode
|
|
20
|
+
│ ├── lastSeen # User activity tracking
|
|
21
|
+
│ └── gotoService
|
|
22
|
+
│ ├── monitor # Request monitoring config
|
|
23
|
+
│ └── renewReqMonitorOff # Disable timeout renewal
|
|
24
|
+
└── oauth
|
|
25
|
+
└── value
|
|
26
|
+
├── roaming # Cross-environment access
|
|
27
|
+
├── pinWrapper # PIN-based login endpoint
|
|
28
|
+
└── pinWhitelist # PIN login API whitelist
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 1. Maintenance Mode
|
|
34
|
+
|
|
35
|
+
**Path:** `registry.custom.gateway.value.maintenanceMode`
|
|
36
|
+
|
|
37
|
+
**Middleware:** `mw/maintenanceMode/index.js`
|
|
38
|
+
|
|
39
|
+
Enables gateway-wide maintenance mode, returning a configurable status to all requests.
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
{
|
|
43
|
+
"maintenanceMode": {
|
|
44
|
+
"on": true, // Enable maintenance mode
|
|
45
|
+
"status": 503, // HTTP status code (default: 503)
|
|
46
|
+
"message": "Maintenance in progress", // Custom message
|
|
47
|
+
"retryAfter": 3600 // Retry-After header in seconds
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Field | Type | Default | Description |
|
|
53
|
+
|-------|------|---------|-------------|
|
|
54
|
+
| `on` | boolean | `false` | Enable/disable maintenance mode |
|
|
55
|
+
| `status` | number | `503` | HTTP status code to return |
|
|
56
|
+
| `message` | string | `"Maintenance mode is on, come back soon"` | Response message |
|
|
57
|
+
| `retryAfter` | number | - | Seconds until retry (sets `Retry-After` header) |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 2. IP Blacklist (IP2Ban)
|
|
62
|
+
|
|
63
|
+
**Path:** `registry.custom.gateway.value.traffic.ip2ban`
|
|
64
|
+
|
|
65
|
+
**Middleware:** `mw/ip2ban/index.js`
|
|
66
|
+
|
|
67
|
+
Blocks specified IP addresses from accessing the gateway entirely.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
{
|
|
71
|
+
"traffic": {
|
|
72
|
+
"ip2ban": ["192.168.1.100", "10.0.0.50", "::1"]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Field | Type | Default | Description |
|
|
78
|
+
|-------|------|---------|-------------|
|
|
79
|
+
| `ip2ban` | string[] | `[]` | Array of IP addresses to block (returns 403) |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 3. Rate Limiting (Throttling)
|
|
84
|
+
|
|
85
|
+
**Path:** `registry.custom.gateway.value.traffic`
|
|
86
|
+
|
|
87
|
+
**Middleware:** `mw/traffic/index.js`
|
|
88
|
+
|
|
89
|
+
Configures rate limiting strategies and storage backend.
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
{
|
|
93
|
+
"traffic": {
|
|
94
|
+
"model": "mongo", // Storage: "memory" or "mongo"
|
|
95
|
+
"throttling": {
|
|
96
|
+
"oauth": { // Service-specific config
|
|
97
|
+
"publicAPIStrategy": "default", // Strategy for public APIs
|
|
98
|
+
"privateAPIStrategy": "heavy", // Strategy for authenticated APIs
|
|
99
|
+
"apis": ["/token", "/authorization"] // Specific APIs to throttle
|
|
100
|
+
},
|
|
101
|
+
"payment": {
|
|
102
|
+
"publicAPIStrategy": "strict",
|
|
103
|
+
"apis": ["/charge", "/refund"]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Field | Type | Default | Description |
|
|
111
|
+
|-------|------|---------|-------------|
|
|
112
|
+
| `model` | string | `"memory"` | Storage backend: `"memory"` or `"mongo"` |
|
|
113
|
+
| `throttling` | object | `{}` | Service-level throttling overrides |
|
|
114
|
+
| `throttling[service].publicAPIStrategy` | string | - | Strategy name for unauthenticated requests |
|
|
115
|
+
| `throttling[service].privateAPIStrategy` | string | - | Strategy name for authenticated requests |
|
|
116
|
+
| `throttling[service].apis` | string[] | - | Specific API paths to apply throttling |
|
|
117
|
+
|
|
118
|
+
**Configuration Cascade (highest to lowest priority):**
|
|
119
|
+
1. Tenant service config: `keyObj.config.gateway.throttling`
|
|
120
|
+
2. Custom registry: `registry.custom.gateway.value.traffic.throttling`
|
|
121
|
+
3. Global default: `registry.serviceConfig.throttling`
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 4. Multi-Tenant IP Whitelist
|
|
126
|
+
|
|
127
|
+
**Path:** `registry.custom.gateway.value.mt.whitelist`
|
|
128
|
+
|
|
129
|
+
**Middleware:** `mw/mt/utils.js`
|
|
130
|
+
|
|
131
|
+
Allows specific IP ranges to bypass ACL and/or OAuth checks.
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
{
|
|
135
|
+
"mt": {
|
|
136
|
+
"whitelist": {
|
|
137
|
+
"ips": ["10.0.0.0/8", "192.168.1.0/24", "172.16.0.0/12"],
|
|
138
|
+
"acl": true, // Skip ACL checks for whitelisted IPs
|
|
139
|
+
"oauth": true // Skip OAuth checks for whitelisted IPs
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
| Field | Type | Default | Description |
|
|
146
|
+
|-------|------|---------|-------------|
|
|
147
|
+
| `ips` | string[] | `[]` | IP addresses/CIDR ranges to whitelist |
|
|
148
|
+
| `acl` | boolean | `false` | Skip ACL validation for whitelisted IPs |
|
|
149
|
+
| `oauth` | boolean | `false` | Skip OAuth validation for whitelisted IPs |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 5. User Activity Tracking (Last Seen)
|
|
154
|
+
|
|
155
|
+
**Path:** `registry.custom.gateway.value.lastSeen`
|
|
156
|
+
|
|
157
|
+
**Middleware:** `mw/lastSeen/index.js`
|
|
158
|
+
|
|
159
|
+
Tracks user activity by notifying a service (typically URAC) of user access.
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
{
|
|
163
|
+
"lastSeen": {
|
|
164
|
+
"active": true, // Enable tracking
|
|
165
|
+
"serviceName": "urac", // Service to notify
|
|
166
|
+
"serviceVersion": "3", // Service version
|
|
167
|
+
"api": "/user/last/seen", // API endpoint
|
|
168
|
+
"network": "internal" // Optional network identifier
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
| Field | Type | Default | Description |
|
|
174
|
+
|-------|------|---------|-------------|
|
|
175
|
+
| `active` | boolean | `false` | Enable/disable activity tracking |
|
|
176
|
+
| `serviceName` | string | `"urac"` | Service to receive notifications |
|
|
177
|
+
| `serviceVersion` | string | `"3"` | Version of the service |
|
|
178
|
+
| `api` | string | `"/user/last/seen"` | API endpoint to call |
|
|
179
|
+
| `network` | string | - | Optional network info sent in request body |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 6. Request Monitoring
|
|
184
|
+
|
|
185
|
+
**Path:** `registry.custom.gateway.value.gotoService.monitor`
|
|
186
|
+
|
|
187
|
+
**Middleware:** `mw/gotoService/redirectToService.js`
|
|
188
|
+
|
|
189
|
+
Controls which services are monitored for metrics collection.
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
{
|
|
193
|
+
"gotoService": {
|
|
194
|
+
"monitor": {
|
|
195
|
+
"blacklist": ["oauth", "urac", "soamonitor"], // Services to NOT monitor
|
|
196
|
+
"whitelist": ["payment", "orders", "users"] // Services to monitor (exclusive)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
| Field | Type | Default | Description |
|
|
203
|
+
|-------|------|---------|-------------|
|
|
204
|
+
| `blacklist` | string[] | `[]` | Services to exclude from monitoring |
|
|
205
|
+
| `whitelist` | string[] | `[]` | If set, ONLY these services are monitored |
|
|
206
|
+
|
|
207
|
+
**Note:** If `whitelist` is defined, only services in the whitelist are monitored. Otherwise, all services except those in the blacklist are monitored.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 7. Request Timeout Renewal
|
|
212
|
+
|
|
213
|
+
**Path:** `registry.custom.gateway.value.gotoService.renewReqMonitorOff`
|
|
214
|
+
|
|
215
|
+
**Middleware:** `mw/gotoService/lib/preRedirect.js`
|
|
216
|
+
|
|
217
|
+
Disables the heartbeat renewal mechanism for long-running requests.
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
{
|
|
221
|
+
"gotoService": {
|
|
222
|
+
"renewReqMonitorOff": true // Disable timeout renewal
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
| Field | Type | Default | Description |
|
|
228
|
+
|-------|------|---------|-------------|
|
|
229
|
+
| `renewReqMonitorOff` | boolean | `false` | Disable request timeout renewal mechanism |
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 8. OAuth Roaming (Cross-Environment)
|
|
234
|
+
|
|
235
|
+
**Path:** `registry.custom.oauth.value.roaming`
|
|
236
|
+
|
|
237
|
+
**Middleware:** `mw/gotoService/roaming.js`
|
|
238
|
+
|
|
239
|
+
Enables cross-environment access for specific services with IP-based whitelisting.
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
{
|
|
243
|
+
"roaming": {
|
|
244
|
+
"services": {
|
|
245
|
+
"oauth": {
|
|
246
|
+
"whitelistips": ["192.144.3.1", "10.0.0.1"]
|
|
247
|
+
},
|
|
248
|
+
"payment": {
|
|
249
|
+
"whitelistips": ["127.0.0.1", "192.168.1.0/24"]
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
| Field | Type | Default | Description |
|
|
257
|
+
|-------|------|---------|-------------|
|
|
258
|
+
| `services` | object | `{}` | Service-specific roaming configuration |
|
|
259
|
+
| `services[name].whitelistips` | string[] | `[]` | IPs allowed to roam to this service |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 9. PIN Login Wrapper
|
|
264
|
+
|
|
265
|
+
**Path:** `registry.custom.oauth.value.pinWrapper`
|
|
266
|
+
|
|
267
|
+
**Middleware:** `mw/mt/utils.js`
|
|
268
|
+
|
|
269
|
+
Defines a custom PIN-based login endpoint that bypasses standard OAuth flow.
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
{
|
|
273
|
+
"pinWrapper": {
|
|
274
|
+
"servicename": "auth-service", // Service providing PIN login
|
|
275
|
+
"apiname": "/pin/login" // API endpoint for PIN login
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
| Field | Type | Default | Description |
|
|
281
|
+
|-------|------|---------|-------------|
|
|
282
|
+
| `servicename` | string | - | Service name providing PIN authentication |
|
|
283
|
+
| `apiname` | string | - | API endpoint path for PIN login |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 10. PIN Login API Whitelist
|
|
288
|
+
|
|
289
|
+
**Path:** `registry.custom.oauth.value.pinWhitelist`
|
|
290
|
+
|
|
291
|
+
**Middleware:** `mw/mt/utils.js`
|
|
292
|
+
|
|
293
|
+
Whitelists specific APIs that can be accessed when a user is PIN-locked (during PIN login flow).
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
{
|
|
297
|
+
"pinWhitelist": {
|
|
298
|
+
"auth-service": {
|
|
299
|
+
"get": {
|
|
300
|
+
"apis": ["/pin/verify", "/pin/status"],
|
|
301
|
+
"regex": ["/api/v[0-9]+/pin/.*"]
|
|
302
|
+
},
|
|
303
|
+
"post": {
|
|
304
|
+
"apis": ["/pin/login", "/pin/reset"],
|
|
305
|
+
"regex": []
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"user-service": {
|
|
309
|
+
"get": {
|
|
310
|
+
"apis": ["/user/minimal"],
|
|
311
|
+
"regex": []
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
| Field | Type | Default | Description |
|
|
319
|
+
|-------|------|---------|-------------|
|
|
320
|
+
| `[service]` | object | - | Service-specific PIN whitelist |
|
|
321
|
+
| `[service].[method].apis` | string[] | `[]` | Exact API paths to whitelist |
|
|
322
|
+
| `[service].[method].regex` | string[] | `[]` | Regex patterns for matching APIs |
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Complete Configuration Example
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// Core DB: custom_registry collection
|
|
330
|
+
{
|
|
331
|
+
"_id": ObjectId("..."),
|
|
332
|
+
"name": "gateway",
|
|
333
|
+
"value": {
|
|
334
|
+
"maintenanceMode": {
|
|
335
|
+
"on": false,
|
|
336
|
+
"status": 503,
|
|
337
|
+
"message": "System maintenance in progress",
|
|
338
|
+
"retryAfter": 1800
|
|
339
|
+
},
|
|
340
|
+
"mt": {
|
|
341
|
+
"whitelist": {
|
|
342
|
+
"ips": ["10.0.0.0/8"],
|
|
343
|
+
"acl": true,
|
|
344
|
+
"oauth": false
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"traffic": {
|
|
348
|
+
"model": "mongo",
|
|
349
|
+
"ip2ban": ["192.168.1.100"],
|
|
350
|
+
"throttling": {
|
|
351
|
+
"oauth": {
|
|
352
|
+
"publicAPIStrategy": "default",
|
|
353
|
+
"apis": ["/token"]
|
|
354
|
+
},
|
|
355
|
+
"payment": {
|
|
356
|
+
"publicAPIStrategy": "strict",
|
|
357
|
+
"privateAPIStrategy": "heavy",
|
|
358
|
+
"apis": ["/charge", "/refund", "/subscribe"]
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
"lastSeen": {
|
|
363
|
+
"active": true,
|
|
364
|
+
"serviceName": "urac",
|
|
365
|
+
"serviceVersion": "3",
|
|
366
|
+
"api": "/user/last/seen",
|
|
367
|
+
"network": "production"
|
|
368
|
+
},
|
|
369
|
+
"gotoService": {
|
|
370
|
+
"monitor": {
|
|
371
|
+
"blacklist": ["soamonitor", "urac"]
|
|
372
|
+
},
|
|
373
|
+
"renewReqMonitorOff": false
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Separate OAuth custom registry entry
|
|
379
|
+
{
|
|
380
|
+
"_id": ObjectId("..."),
|
|
381
|
+
"name": "oauth",
|
|
382
|
+
"value": {
|
|
383
|
+
"roaming": {
|
|
384
|
+
"services": {
|
|
385
|
+
"oauth": {
|
|
386
|
+
"whitelistips": ["192.144.3.1"]
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
"pinWrapper": {
|
|
391
|
+
"servicename": "auth",
|
|
392
|
+
"apiname": "/pin/login"
|
|
393
|
+
},
|
|
394
|
+
"pinWhitelist": {
|
|
395
|
+
"auth": {
|
|
396
|
+
"post": {
|
|
397
|
+
"apis": ["/pin/login", "/pin/verify"],
|
|
398
|
+
"regex": []
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Middleware Processing Order
|
|
409
|
+
|
|
410
|
+
Custom registry configurations are processed in this order:
|
|
411
|
+
|
|
412
|
+
| Order | Middleware | Configuration Used |
|
|
413
|
+
|-------|------------|-------------------|
|
|
414
|
+
| 1 | ip2ban | `traffic.ip2ban` |
|
|
415
|
+
| 2 | maintenanceMode | `maintenanceMode` |
|
|
416
|
+
| 3 | gotoService/roaming | `oauth.value.roaming` |
|
|
417
|
+
| 4 | gotoService/preRedirect | `gotoService.renewReqMonitorOff` |
|
|
418
|
+
| 5 | gotoService/redirectToService | `gotoService.monitor` |
|
|
419
|
+
| 6 | mt (security checks) | `mt.whitelist`, `oauth.value.pinWrapper`, `oauth.value.pinWhitelist` |
|
|
420
|
+
| 7 | traffic | `traffic.model`, `traffic.throttling` |
|
|
421
|
+
| 8 | lastSeen | `lastSeen` |
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Services Config (Tenant Key Configuration)
|
|
2
|
+
|
|
3
|
+
Tenant key-specific configuration stored in `keyObj.config`. These settings are specific to each tenant's external key and override environment-level settings.
|
|
4
|
+
|
|
5
|
+
## Configuration Structure Overview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
keyObj.config
|
|
9
|
+
├── gateway
|
|
10
|
+
│ ├── networkPackages # Network-based package override
|
|
11
|
+
│ ├── validateTokenAccount # Token account validation
|
|
12
|
+
│ └── throttling # Tenant-specific throttling
|
|
13
|
+
└── [serviceName] # Service URL override
|
|
14
|
+
├── url # Single URL for all versions
|
|
15
|
+
└── urls # Version-specific URLs
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Network Package Override
|
|
21
|
+
|
|
22
|
+
**Path:** `keyObj.config.gateway.networkPackages`
|
|
23
|
+
|
|
24
|
+
**Middlewares:**
|
|
25
|
+
- `mw/key/index.js` (default package)
|
|
26
|
+
- `mw/mt/urac.js` (user packages)
|
|
27
|
+
|
|
28
|
+
Allows different packages to be loaded based on the network identifier configured in the custom registry.
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
{
|
|
32
|
+
"gateway": {
|
|
33
|
+
"networkPackages": {
|
|
34
|
+
"mw": { // Network identifier (from lastSeen.network)
|
|
35
|
+
"AVAPP": { // Product code (keyObj.application.product)
|
|
36
|
+
"default": "AVAPP_DEFAU", // Default package to use for this network
|
|
37
|
+
"users": { // User-specific package mappings
|
|
38
|
+
"AVAPP_EXMPL": "AVAPP_ALTRN" // Map user's package to alternate
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### How it Works
|
|
48
|
+
|
|
49
|
+
The network package override operates at two levels:
|
|
50
|
+
|
|
51
|
+
**1. Key Middleware** (`mw/key/index.js`) - Applies `default` package override for all requests
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
1. Get network from registry
|
|
55
|
+
network = registry.custom.gateway.value.lastSeen.network (e.g., "mw")
|
|
56
|
+
|
|
57
|
+
2. Get product from keyObj
|
|
58
|
+
product = keyObj.application.product (e.g., "AVAPP")
|
|
59
|
+
|
|
60
|
+
3. Check for network package config
|
|
61
|
+
config = keyObj.config.gateway.networkPackages[network][product]
|
|
62
|
+
|
|
63
|
+
4. If config.default exists:
|
|
64
|
+
├── Original: keyObj.application.package = "AVAPP_EXMPL"
|
|
65
|
+
├── Override: keyObj.application.package = "AVAPP_DEFAU"
|
|
66
|
+
└── Log: "Network package override: replaced package [AVAPP_EXMPL]
|
|
67
|
+
with [AVAPP_DEFAU] for network [mw] and product [AVAPP]"
|
|
68
|
+
|
|
69
|
+
5. Continue to load the (possibly overridden) package
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**2. MT Middleware** (`mw/mt/urac.js`) - Applies `users` package override for authenticated user's allowed packages
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
In resolveACL() before calling getPackagesData():
|
|
76
|
+
|
|
77
|
+
1. Get network from registry
|
|
78
|
+
network = registry.custom.gateway.value.lastSeen.network (e.g., "mw")
|
|
79
|
+
|
|
80
|
+
2. Get product from soajs.tenant.application.product (e.g., "AVAPP")
|
|
81
|
+
|
|
82
|
+
3. Get user's allowed packages
|
|
83
|
+
allowedPackages = userRecord.groupsConfig.allowedPackages[product]
|
|
84
|
+
(e.g., ["AVAPP_EXMPL"])
|
|
85
|
+
|
|
86
|
+
4. Check for network package config
|
|
87
|
+
config = keyObj.config.gateway.networkPackages[network][product]
|
|
88
|
+
|
|
89
|
+
5. If config.users exists, for each package in allowedPackages:
|
|
90
|
+
├── Check: config.users["AVAPP_EXMPL"] = "AVAPP_ALTRN"
|
|
91
|
+
├── Replace: allowedPackages[i] = "AVAPP_ALTRN"
|
|
92
|
+
└── Log: "User network package override: replaced package [AVAPP_EXMPL]
|
|
93
|
+
with [AVAPP_ALTRN] for network [mw] and product [AVAPP]"
|
|
94
|
+
|
|
95
|
+
6. Call getPackagesData() with the (possibly modified) allowedPackages
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
| Field | Type | Description |
|
|
99
|
+
|-------|------|-------------|
|
|
100
|
+
| `networkPackages` | object | Top-level container for network-based package configs |
|
|
101
|
+
| `networkPackages[network]` | object | Config for a specific network (e.g., "mw") |
|
|
102
|
+
| `networkPackages[network][product]` | object | Config for a specific product |
|
|
103
|
+
| `networkPackages[network][product].default` | string | Default package for key middleware (tenant-level) |
|
|
104
|
+
| `networkPackages[network][product].users` | object | User-specific package mappings for mt middleware |
|
|
105
|
+
| `networkPackages[network][product].users[packageCode]` | string | Replacement package for this user's package |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 2. Validate Token Account
|
|
110
|
+
|
|
111
|
+
**Path:** `keyObj.config.gateway.validateTokenAccount`
|
|
112
|
+
|
|
113
|
+
**Middleware:** `mw/mt/utils.js` → `uracCheck()`
|
|
114
|
+
|
|
115
|
+
Forces users to re-login when their email or phone changes, providing additional security for sensitive account changes.
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
{
|
|
119
|
+
"gateway": {
|
|
120
|
+
"validateTokenAccount": {
|
|
121
|
+
"email": true, // Validate email hasn't changed
|
|
122
|
+
"phone": true // Validate phone hasn't changed
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### How it Works
|
|
129
|
+
|
|
130
|
+
- When a user's OAuth token is validated, the middleware compares the current user profile with the token's stored user data
|
|
131
|
+
- If `email: true` and the user's email has changed since token creation → Error 146 (invalid token)
|
|
132
|
+
- If `phone: true` and the user's phone has changed since token creation → Error 146 (invalid token)
|
|
133
|
+
- This forces users to re-authenticate after changing sensitive account information
|
|
134
|
+
|
|
135
|
+
| Field | Type | Default | Description |
|
|
136
|
+
|-------|------|---------|-------------|
|
|
137
|
+
| `validateTokenAccount.email` | boolean | `false` | Invalidate token if email changed |
|
|
138
|
+
| `validateTokenAccount.phone` | boolean | `false` | Invalidate token if phone changed |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 3. Tenant-Specific Throttling
|
|
143
|
+
|
|
144
|
+
**Path:** `keyObj.config.gateway.throttling`
|
|
145
|
+
|
|
146
|
+
**Middleware:** `mw/traffic/index.js`
|
|
147
|
+
|
|
148
|
+
Allows overriding the global throttling configuration at the tenant level.
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
{
|
|
152
|
+
"gateway": {
|
|
153
|
+
"throttling": {
|
|
154
|
+
"serviceName": { // Service to apply throttling to
|
|
155
|
+
"publicAPIStrategy": "default", // Strategy for unauthenticated requests
|
|
156
|
+
"privateAPIStrategy": "heavy", // Strategy for authenticated requests
|
|
157
|
+
"apis": ["/api1", "/api2"] // Optional: specific APIs (if omitted, applies to all)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Configuration Cascade
|
|
165
|
+
|
|
166
|
+
Throttling configuration is resolved in this order (highest to lowest priority):
|
|
167
|
+
|
|
168
|
+
1. `keyObj.config.gateway.throttling` (tenant service config)
|
|
169
|
+
2. `registry.custom.gateway.value.traffic.throttling` (custom registry)
|
|
170
|
+
3. `registry.serviceConfig.throttling` (global default)
|
|
171
|
+
|
|
172
|
+
| Field | Type | Description |
|
|
173
|
+
|-------|------|-------------|
|
|
174
|
+
| `throttling[service]` | object | Throttling config for a specific service |
|
|
175
|
+
| `throttling[service].publicAPIStrategy` | string | Strategy name for unauthenticated requests |
|
|
176
|
+
| `throttling[service].privateAPIStrategy` | string | Strategy name for authenticated requests |
|
|
177
|
+
| `throttling[service].apis` | string[] | Optional: specific APIs to throttle (all if omitted) |
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 4. Service URL Override
|
|
182
|
+
|
|
183
|
+
**Path:** `keyObj.config[serviceName]`
|
|
184
|
+
|
|
185
|
+
**Middleware:** `mw/gotoService/lib/preRedirect.js`
|
|
186
|
+
|
|
187
|
+
Allows tenants to override the URL for specific services, useful for pointing to custom endpoints or different service versions.
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
{
|
|
191
|
+
"urac": { // Service name
|
|
192
|
+
"url": "https://custom-urac.example.com" // Custom URL (overrides registry)
|
|
193
|
+
},
|
|
194
|
+
"oauth": { // Another service
|
|
195
|
+
"urls": [ // Versioned URLs
|
|
196
|
+
{ "version": "1", "url": "https://oauth-v1.example.com" },
|
|
197
|
+
{ "version": "2", "url": "https://oauth-v2.example.com" }
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### How it Works
|
|
204
|
+
|
|
205
|
+
- For endpoint-type services, the gateway checks `keyObj.config[serviceName]`
|
|
206
|
+
- If `url` exists, it overrides the registry URL
|
|
207
|
+
- If `urls` array exists and matches the requested version, that versioned URL is used
|
|
208
|
+
- This allows per-tenant service routing without modifying the global registry
|
|
209
|
+
|
|
210
|
+
| Field | Type | Description |
|
|
211
|
+
|-------|------|-------------|
|
|
212
|
+
| `config[service].url` | string | Custom URL for all versions of this service |
|
|
213
|
+
| `config[service].urls` | array | Array of version-specific URLs |
|
|
214
|
+
| `config[service].urls[].version` | string | Service version |
|
|
215
|
+
| `config[service].urls[].url` | string | URL for this specific version |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Complete Configuration Example
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
// In tenant key configuration (keyObj.config)
|
|
223
|
+
{
|
|
224
|
+
"gateway": {
|
|
225
|
+
"networkPackages": {
|
|
226
|
+
"mw": {
|
|
227
|
+
"AVAPP": {
|
|
228
|
+
"default": "AVAPP_DEFAU",
|
|
229
|
+
"users": {
|
|
230
|
+
"AVAPP_EXMPL": "AVAPP_ALTRN",
|
|
231
|
+
"AVAPP_BASIC": "AVAPP_BASIC_MW"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"partner": {
|
|
236
|
+
"AVAPP": {
|
|
237
|
+
"default": "AVAPP_PARTNER",
|
|
238
|
+
"users": {}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"validateTokenAccount": {
|
|
243
|
+
"email": true,
|
|
244
|
+
"phone": false
|
|
245
|
+
},
|
|
246
|
+
"throttling": {
|
|
247
|
+
"payment": {
|
|
248
|
+
"publicAPIStrategy": "strict",
|
|
249
|
+
"privateAPIStrategy": "premium",
|
|
250
|
+
"apis": ["/charge", "/refund"]
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"urac": {
|
|
255
|
+
"url": "https://custom-urac.tenant.com"
|
|
256
|
+
},
|
|
257
|
+
"oauth": {
|
|
258
|
+
"urls": [
|
|
259
|
+
{ "version": "1", "url": "https://oauth-v1.tenant.com" },
|
|
260
|
+
{ "version": "2", "url": "https://oauth-v2.tenant.com" }
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Error Codes
|
|
269
|
+
|
|
270
|
+
| Code | Description |
|
|
271
|
+
|------|-------------|
|
|
272
|
+
| 144 | External key is not valid for this environment |
|
|
273
|
+
| 146 | Invalid token (account validation failed - email/phone changed) |
|
|
274
|
+
| 148 | External key is invalid or has been disabled |
|
|
275
|
+
| 149 | Product package not found |
|