soajs.controller 4.2.42 → 4.2.43
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 +92 -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 +188 -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 +7 -7
- 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,139 @@
|
|
|
1
|
+
# Key ACL Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/keyACL/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 12
|
|
6
|
+
|
|
7
|
+
The Key ACL middleware extracts and processes the Access Control List (ACL) from the tenant's key or package.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Extracts ACL for the requested service
|
|
12
|
+
- Resolves ACL from application or package level
|
|
13
|
+
- Handles both old and new ACL schema formats
|
|
14
|
+
- Supports version-specific and method-specific ACL
|
|
15
|
+
|
|
16
|
+
## Flow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Incoming Request (after key middleware)
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────┐
|
|
23
|
+
│ Have keyObj │ keyObj && packObj exist?
|
|
24
|
+
│ and packObj? │
|
|
25
|
+
└────────┬────────┘
|
|
26
|
+
│
|
|
27
|
+
├─── No ──▶ next()
|
|
28
|
+
│
|
|
29
|
+
▼
|
|
30
|
+
┌─────────────────────────┐
|
|
31
|
+
│ Extract ACL │ Priority:
|
|
32
|
+
│ for Service │ 1. keyObj.application.acl
|
|
33
|
+
└────────┬────────────────┘ 2. packObj.acl
|
|
34
|
+
│
|
|
35
|
+
▼
|
|
36
|
+
┌─────────────────────────┐
|
|
37
|
+
│ Detect Schema Type │ Old: apis/apisRegExp at root
|
|
38
|
+
│ │ New: versioned with methods
|
|
39
|
+
└────────┬────────────────┘
|
|
40
|
+
│
|
|
41
|
+
▼
|
|
42
|
+
┌─────────────────────────┐
|
|
43
|
+
│ Resolve Version │ Match requested version
|
|
44
|
+
│ (if versioned) │ or get latest from ACL
|
|
45
|
+
└────────┬────────────────┘
|
|
46
|
+
│
|
|
47
|
+
▼
|
|
48
|
+
┌─────────────────────────┐
|
|
49
|
+
│ Extract Method- │ get, post, put, delete
|
|
50
|
+
│ Specific ACL │
|
|
51
|
+
└────────┬────────────────┘
|
|
52
|
+
│
|
|
53
|
+
▼
|
|
54
|
+
┌─────────────────────────┐
|
|
55
|
+
│ Store finalAcl │ req.soajs.controller.serviceParams.finalAcl
|
|
56
|
+
└────────┬────────────────┘
|
|
57
|
+
│
|
|
58
|
+
▼
|
|
59
|
+
next()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## ACL Resolution Priority
|
|
63
|
+
|
|
64
|
+
1. **Application ACL** - `keyObj.application.acl[serviceName]`
|
|
65
|
+
2. **Package ACL** - `packObj.acl[serviceName]`
|
|
66
|
+
|
|
67
|
+
## ACL Schema Formats
|
|
68
|
+
|
|
69
|
+
### Old Schema (Deprecated)
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
{
|
|
73
|
+
"serviceName": {
|
|
74
|
+
"access": true,
|
|
75
|
+
"apis": {
|
|
76
|
+
"/api/path": { "access": ["group1"] }
|
|
77
|
+
},
|
|
78
|
+
"apisRegExp": [
|
|
79
|
+
{ "regExp": /^\/api\/.*/, "access": ["group2"] }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### New Schema (Versioned)
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
{
|
|
89
|
+
"serviceName": {
|
|
90
|
+
"1": { // Version
|
|
91
|
+
"access": true,
|
|
92
|
+
"apisPermission": "restricted",
|
|
93
|
+
"get": {
|
|
94
|
+
"apis": { "/user": {} }
|
|
95
|
+
},
|
|
96
|
+
"post": {
|
|
97
|
+
"apis": { "/user": { "access": ["admin"] } }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### New Schema (Method-Based, Non-Versioned)
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
{
|
|
108
|
+
"serviceName": {
|
|
109
|
+
"access": true,
|
|
110
|
+
"apisPermission": "restricted",
|
|
111
|
+
"get": {
|
|
112
|
+
"apis": { "/user": {} }
|
|
113
|
+
},
|
|
114
|
+
"post": {
|
|
115
|
+
"apis": { "/user": { "access": ["admin"] } }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Properties Set
|
|
122
|
+
|
|
123
|
+
| Property | Description |
|
|
124
|
+
|----------|-------------|
|
|
125
|
+
| `req.soajs.controller.serviceParams.finalAcl` | Processed ACL for the service |
|
|
126
|
+
|
|
127
|
+
## Error Codes
|
|
128
|
+
|
|
129
|
+
| Code | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| 154 | Requested version not found in ACL |
|
|
132
|
+
|
|
133
|
+
## Usage Notes
|
|
134
|
+
|
|
135
|
+
- Runs after key middleware loads keyObj and packObj
|
|
136
|
+
- Application-level ACL overrides package ACL
|
|
137
|
+
- If no version specified, uses latest version from ACL
|
|
138
|
+
- Converts regex patterns for API matching
|
|
139
|
+
- Method-specific ACL inherits service-level `access` and `apisPermission`
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# LastSeen Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/lastSeen/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 17
|
|
6
|
+
|
|
7
|
+
The LastSeen middleware asynchronously notifies a service (typically URAC) of user activity for tracking purposes.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Tracks user activity (last seen time)
|
|
12
|
+
- Asynchronous notification (non-blocking)
|
|
13
|
+
- Configurable service endpoint
|
|
14
|
+
- Only tracks authenticated users
|
|
15
|
+
|
|
16
|
+
## Flow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Incoming Request (after OAuth/MT)
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────┐
|
|
23
|
+
│ Call next() │ Continue immediately (non-blocking)
|
|
24
|
+
└────────┬────────┘
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
┌─────────────────────────┐
|
|
28
|
+
│ Have URAC Driver? │ req.soajs.uracDriver exists?
|
|
29
|
+
└────────┬────────────────┘
|
|
30
|
+
│
|
|
31
|
+
├─── No ──▶ (done)
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌─────────────────────────┐
|
|
35
|
+
│ LastSeen Active? │ custom.gateway.value.lastSeen.active?
|
|
36
|
+
└────────┬────────────────┘
|
|
37
|
+
│
|
|
38
|
+
├─── No ──▶ (done)
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
┌─────────────────────────┐
|
|
42
|
+
│ Get User ID │ From URAC profile
|
|
43
|
+
└────────┬────────────────┘
|
|
44
|
+
│
|
|
45
|
+
├─── No user ID ──▶ (done, log debug)
|
|
46
|
+
│
|
|
47
|
+
▼
|
|
48
|
+
┌─────────────────────────┐
|
|
49
|
+
│ Resolve Service Host │ awareness.getHost()
|
|
50
|
+
└────────┬────────────────┘
|
|
51
|
+
│
|
|
52
|
+
├─── No host ──▶ (done, log debug)
|
|
53
|
+
│
|
|
54
|
+
▼
|
|
55
|
+
┌─────────────────────────┐
|
|
56
|
+
│ POST to LastSeen │ http://host:port/api
|
|
57
|
+
│ API (async) │ body: { network: ... }
|
|
58
|
+
└─────────────────────────┘
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
Located in `registry.custom.gateway.value.lastSeen`:
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
{
|
|
67
|
+
"lastSeen": {
|
|
68
|
+
"active": true, // Enable tracking
|
|
69
|
+
"serviceName": "urac", // Target service
|
|
70
|
+
"serviceVersion": "3", // Service version
|
|
71
|
+
"api": "/user/last/seen", // API endpoint
|
|
72
|
+
"network": "internal" // Optional network identifier
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Field | Type | Default | Description |
|
|
78
|
+
|-------|------|---------|-------------|
|
|
79
|
+
| `active` | boolean | `false` | Enable/disable tracking |
|
|
80
|
+
| `serviceName` | string | `"urac"` | Service to notify |
|
|
81
|
+
| `serviceVersion` | string | `"3"` | Service version |
|
|
82
|
+
| `api` | string | `"/user/last/seen"` | API endpoint |
|
|
83
|
+
| `network` | string | - | Network identifier in request body |
|
|
84
|
+
|
|
85
|
+
## Request to URAC
|
|
86
|
+
|
|
87
|
+
**Method:** POST
|
|
88
|
+
|
|
89
|
+
**URL:** `http://{host}:{port}/user/last/seen`
|
|
90
|
+
|
|
91
|
+
**Headers:**
|
|
92
|
+
```
|
|
93
|
+
Content-Type: application/json
|
|
94
|
+
soajsinjectobj: <inject object from MT middleware>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Body:**
|
|
98
|
+
```javascript
|
|
99
|
+
{
|
|
100
|
+
"network": "internal" // If configured
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Usage Notes
|
|
105
|
+
|
|
106
|
+
- Non-blocking: calls `next()` immediately
|
|
107
|
+
- Only activates for authenticated users with URAC profile
|
|
108
|
+
- Errors are logged but don't affect the request
|
|
109
|
+
- Uses awareness for service host resolution
|
|
110
|
+
- Forwards `soajsinjectobj` header for authentication context
|
|
111
|
+
- Network identifier useful for tracking activity by location/network
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Maintenance Mode Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/maintenanceMode/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 7
|
|
6
|
+
|
|
7
|
+
The Maintenance Mode middleware returns a configurable response when the gateway is in maintenance mode.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Blocks all requests when maintenance mode is enabled
|
|
12
|
+
- Returns configurable status code and message
|
|
13
|
+
- Supports `Retry-After` header for clients
|
|
14
|
+
|
|
15
|
+
## Flow
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Incoming Request
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
┌─────────────────────┐
|
|
22
|
+
│ Get Maintenance │ registry.custom.gateway.value.maintenanceMode
|
|
23
|
+
│ Mode Config │
|
|
24
|
+
└────────┬────────────┘
|
|
25
|
+
│
|
|
26
|
+
▼
|
|
27
|
+
┌─────────────────────┐
|
|
28
|
+
│ Maintenance │ maintenanceMode.on === true?
|
|
29
|
+
│ Enabled? │
|
|
30
|
+
└────────┬────────────┘
|
|
31
|
+
│
|
|
32
|
+
├─── Yes ──▶ Return configured status/message
|
|
33
|
+
│ Set Retry-After header if configured
|
|
34
|
+
▼
|
|
35
|
+
next()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Configuration
|
|
39
|
+
|
|
40
|
+
Located in `registry.custom.gateway.value.maintenanceMode`:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
{
|
|
44
|
+
"maintenanceMode": {
|
|
45
|
+
"on": true, // Enable maintenance mode
|
|
46
|
+
"status": 503, // HTTP status code
|
|
47
|
+
"message": "System maintenance", // Response message
|
|
48
|
+
"retryAfter": 3600 // Retry-After header (seconds)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
| Field | Type | Default | Description |
|
|
54
|
+
|-------|------|---------|-------------|
|
|
55
|
+
| `on` | boolean | `false` | Enable/disable maintenance mode |
|
|
56
|
+
| `status` | number | `503` | HTTP status code |
|
|
57
|
+
| `message` | string | `"Maintenance mode is on, come back soon"` | Response message |
|
|
58
|
+
| `retryAfter` | number | - | Seconds until retry |
|
|
59
|
+
|
|
60
|
+
## Response
|
|
61
|
+
|
|
62
|
+
When maintenance mode is enabled:
|
|
63
|
+
```
|
|
64
|
+
HTTP/1.1 503 Service Unavailable
|
|
65
|
+
Content-Type: application/json
|
|
66
|
+
Retry-After: 3600
|
|
67
|
+
|
|
68
|
+
{
|
|
69
|
+
"result": false,
|
|
70
|
+
"errors": {
|
|
71
|
+
"codes": [xxx],
|
|
72
|
+
"details": [{ "code": xxx, "message": "System maintenance" }]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Usage Notes
|
|
78
|
+
|
|
79
|
+
- All requests blocked when enabled (no exceptions)
|
|
80
|
+
- Configure via Core DB custom registry
|
|
81
|
+
- Use maintenance port (5000) for health checks during maintenance
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# MT (Multi-Tenant) Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/mt/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 14
|
|
6
|
+
|
|
7
|
+
The MT middleware handles multi-tenant security checks, URAC integration, and prepares the injection header for target services.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Enforces multi-tenant security pipeline
|
|
12
|
+
- Loads tenant and application context
|
|
13
|
+
- Integrates with URAC for user profiles
|
|
14
|
+
- Prepares `soajsinjectobj` header for downstream services
|
|
15
|
+
|
|
16
|
+
## Flow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Incoming Request
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────────────┐
|
|
23
|
+
│ Is Proxy Route? │ Skip security for proxy
|
|
24
|
+
└────────┬────────────────┘
|
|
25
|
+
│
|
|
26
|
+
├─── Yes ──▶ Execute OAuth check → next()
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
┌─────────────────────────┐
|
|
30
|
+
│ External Key │ Based on service config
|
|
31
|
+
│ Required? │
|
|
32
|
+
└────────┬────────────────┘
|
|
33
|
+
│
|
|
34
|
+
├─── No ──▶ Mark as public API → OAuth check
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
┌─────────────────────────┐
|
|
38
|
+
│ Load Tenant Context │ From keyObj
|
|
39
|
+
└────────┬────────────────┘
|
|
40
|
+
│
|
|
41
|
+
▼
|
|
42
|
+
┌─────────────────────────┐
|
|
43
|
+
│ Security Pipeline │ Waterfall checks:
|
|
44
|
+
│ │ 1. IP Whitelist
|
|
45
|
+
│ │ 2. Geo Check
|
|
46
|
+
│ │ 3. Device Check
|
|
47
|
+
│ │ 4. ACL Check
|
|
48
|
+
│ │ 5. OAuth Check (if required)
|
|
49
|
+
│ │ 6. URAC Check
|
|
50
|
+
│ │ 7. URAC ACL Check
|
|
51
|
+
│ │ 8. Service Check
|
|
52
|
+
│ │ 9. API Check
|
|
53
|
+
└────────┬────────────────┘
|
|
54
|
+
│
|
|
55
|
+
├─── Any check fails ──▶ Error response
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
┌─────────────────────────┐
|
|
59
|
+
│ Build Inject Object │ Tenant, key, app, user info
|
|
60
|
+
└────────┬────────────────┘
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
┌─────────────────────────┐
|
|
64
|
+
│ Resolve InterConnect │ Service-to-service awareness
|
|
65
|
+
│ (if configured) │
|
|
66
|
+
└────────┬────────────────┘
|
|
67
|
+
│
|
|
68
|
+
▼
|
|
69
|
+
┌─────────────────────────┐
|
|
70
|
+
│ Set soajsinjectobj │ req.headers.soajsinjectobj = JSON
|
|
71
|
+
│ Header │
|
|
72
|
+
└────────┬────────────────┘
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
next()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Security Pipeline (utils.js)
|
|
79
|
+
|
|
80
|
+
| Order | Check | Description |
|
|
81
|
+
|-------|-------|-------------|
|
|
82
|
+
| 1 | `ipWhitelist` | Validates IP against whitelist |
|
|
83
|
+
| 2 | `securityGeoCheck` | Validates geographic location |
|
|
84
|
+
| 3 | `securityDeviceCheck` | Validates device fingerprint |
|
|
85
|
+
| 4 | `aclCheck` | Validates service-level ACL |
|
|
86
|
+
| 5 | `oauthCheck` | Validates OAuth token (if required) |
|
|
87
|
+
| 6 | `uracCheck` | Loads user profile from URAC |
|
|
88
|
+
| 7 | `aclUrackCheck` | Validates user-specific ACL |
|
|
89
|
+
| 8 | `serviceCheck` | Validates service access |
|
|
90
|
+
| 9 | `apiCheck` | Validates API access |
|
|
91
|
+
|
|
92
|
+
## Injection Object Structure
|
|
93
|
+
|
|
94
|
+
The `soajsinjectobj` header contains:
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
{
|
|
98
|
+
"tenant": {
|
|
99
|
+
"id": "tenant_id",
|
|
100
|
+
"name": "Tenant Name",
|
|
101
|
+
"code": "TCODE",
|
|
102
|
+
"locked": false,
|
|
103
|
+
"roaming": null,
|
|
104
|
+
"type": "product",
|
|
105
|
+
"main": { ... }, // If client tenant
|
|
106
|
+
"profile": { ... } // If tenant_Profile enabled
|
|
107
|
+
},
|
|
108
|
+
"key": {
|
|
109
|
+
"config": { ... },
|
|
110
|
+
"iKey": "internal_key",
|
|
111
|
+
"eKey": "external_key"
|
|
112
|
+
},
|
|
113
|
+
"application": {
|
|
114
|
+
"product": "PRODUCT",
|
|
115
|
+
"package": "PACKAGE",
|
|
116
|
+
"appId": "app_id",
|
|
117
|
+
"acl": { ... }, // If provision_ACL enabled
|
|
118
|
+
"acl_all_env": { ... }
|
|
119
|
+
},
|
|
120
|
+
"package": {
|
|
121
|
+
"acl": { ... }, // If provision_ACL enabled
|
|
122
|
+
"acl_all_env": { ... }
|
|
123
|
+
},
|
|
124
|
+
"device": { ... },
|
|
125
|
+
"geo": { ... },
|
|
126
|
+
"awareness": {
|
|
127
|
+
"host": "controller_host",
|
|
128
|
+
"port": 4000,
|
|
129
|
+
"interConnect": [...] // If configured
|
|
130
|
+
},
|
|
131
|
+
"urac": { // If authenticated
|
|
132
|
+
"_id": "user_id",
|
|
133
|
+
"username": "user",
|
|
134
|
+
"firstName": "John",
|
|
135
|
+
"lastName": "Doe",
|
|
136
|
+
"email": "user@example.com",
|
|
137
|
+
"groups": ["group1"],
|
|
138
|
+
"tenant": { "id": "...", "code": "..." },
|
|
139
|
+
"profile": { ... }, // If urac_Profile enabled
|
|
140
|
+
"acl": { ... }, // If urac_ACL enabled
|
|
141
|
+
"config": { ... }, // If urac_Config enabled
|
|
142
|
+
"groupsConfig": { ... } // If urac_GroupConfig enabled
|
|
143
|
+
},
|
|
144
|
+
"param": {
|
|
145
|
+
"urac_Profile": true,
|
|
146
|
+
"urac_ACL": true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Service Parameters
|
|
152
|
+
|
|
153
|
+
Service-level configuration that affects MT processing:
|
|
154
|
+
|
|
155
|
+
| Parameter | Description |
|
|
156
|
+
|-----------|-------------|
|
|
157
|
+
| `urac` | Include URAC user info |
|
|
158
|
+
| `urac_Profile` | Include user profile |
|
|
159
|
+
| `urac_ACL` | Include user ACL |
|
|
160
|
+
| `urac_Config` | Include user config |
|
|
161
|
+
| `urac_GroupConfig` | Include group config |
|
|
162
|
+
| `tenant_Profile` | Include tenant profile |
|
|
163
|
+
| `provision_ACL` | Include full ACL data |
|
|
164
|
+
| `extKeyRequired` | Require external key |
|
|
165
|
+
| `oauth` | Require OAuth token |
|
|
166
|
+
| `interConnect` | Service-to-service discovery |
|
|
167
|
+
|
|
168
|
+
## Error Codes
|
|
169
|
+
|
|
170
|
+
| Code | Description |
|
|
171
|
+
|------|-------------|
|
|
172
|
+
| 133 | Service version not found |
|
|
173
|
+
| 135 | Inject header too large |
|
|
174
|
+
| 152 | Package not loaded |
|
|
175
|
+
| 153 | Key not loaded |
|
|
176
|
+
| 158 | Login required for ACL route |
|
|
177
|
+
|
|
178
|
+
## Related Files
|
|
179
|
+
|
|
180
|
+
- `mw/mt/utils.js` - Security check implementations
|
|
181
|
+
- `mw/mt/urac.js` - URAC driver integration
|
|
182
|
+
|
|
183
|
+
## Usage Notes
|
|
184
|
+
|
|
185
|
+
- Proxy routes bypass all MT checks except OAuth
|
|
186
|
+
- Header size limited by `SOAJS_MAX_INJECT_HEADER_SIZE` (default: 64KB)
|
|
187
|
+
- InterConnect enables service-to-service awareness info
|
|
188
|
+
- URAC integration loads user profile asynchronously
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# OAuth Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/oauth/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 15
|
|
6
|
+
|
|
7
|
+
The OAuth middleware handles authentication by validating OAuth2 tokens or JWT tokens.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Validates OAuth2 access tokens via oauth2-server
|
|
12
|
+
- Validates JWT tokens via jsonwebtoken
|
|
13
|
+
- Supports tenant-specific OAuth configuration
|
|
14
|
+
- Sets `req.oauth` with token information
|
|
15
|
+
|
|
16
|
+
## Flow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Incoming Request
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────────────┐
|
|
23
|
+
│ Determine OAuth Type │ tenantOauth.type or
|
|
24
|
+
│ │ registry.serviceConfig.oauth.type
|
|
25
|
+
└────────┬────────────────┘
|
|
26
|
+
│
|
|
27
|
+
├─── Type 0 (JWT) ──▶ JWT Validation
|
|
28
|
+
│
|
|
29
|
+
├─── Type 2 (OAuth2) ──▶ OAuth2 Server Validation
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
┌─────────────────────────┐
|
|
33
|
+
│ Set req.oauth │ { bearerToken, type }
|
|
34
|
+
└────────┬────────────────┘
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
next() or Error
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## OAuth Types
|
|
41
|
+
|
|
42
|
+
### Type 2: OAuth2 (Default)
|
|
43
|
+
|
|
44
|
+
Uses oauth2-server library for token validation.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Request with access_token
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
┌─────────────────────────┐
|
|
51
|
+
│ oauth2-server │ Validates token against DB
|
|
52
|
+
│ authorise() │
|
|
53
|
+
└────────┬────────────────┘
|
|
54
|
+
│
|
|
55
|
+
├─── Invalid ──▶ OAuth2Error
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
┌─────────────────────────┐
|
|
59
|
+
│ req.oauth = { │
|
|
60
|
+
│ bearerToken: user, │
|
|
61
|
+
│ type: 2 │
|
|
62
|
+
│ } │
|
|
63
|
+
└─────────────────────────┘
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Type 0: JWT
|
|
67
|
+
|
|
68
|
+
Uses jsonwebtoken library for JWT validation.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Request with Authorization: Bearer <jwt>
|
|
72
|
+
│
|
|
73
|
+
▼
|
|
74
|
+
┌─────────────────────────┐
|
|
75
|
+
│ Extract Bearer Token │ from Authorization header
|
|
76
|
+
└────────┬────────────────┘
|
|
77
|
+
│
|
|
78
|
+
├─── No match ──▶ Error 143
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
┌─────────────────────────┐
|
|
82
|
+
│ jwt.verify() │ Using secret and algorithms
|
|
83
|
+
└────────┬────────────────┘
|
|
84
|
+
│
|
|
85
|
+
├─── Invalid ──▶ Error 143
|
|
86
|
+
│
|
|
87
|
+
▼
|
|
88
|
+
┌─────────────────────────┐
|
|
89
|
+
│ req.oauth = { │
|
|
90
|
+
│ bearerToken: decoded,│
|
|
91
|
+
│ type: 0 │
|
|
92
|
+
│ } │
|
|
93
|
+
└─────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Configuration
|
|
97
|
+
|
|
98
|
+
### OAuth2 Configuration
|
|
99
|
+
|
|
100
|
+
Located in `registry.serviceConfig.oauth`:
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
{
|
|
104
|
+
"oauth": {
|
|
105
|
+
"type": 2,
|
|
106
|
+
"grants": ["password", "refresh_token"],
|
|
107
|
+
"debug": false,
|
|
108
|
+
"accessTokenLifetime": 7200,
|
|
109
|
+
"refreshTokenLifetime": 1209600
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### JWT Configuration
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
{
|
|
118
|
+
"oauth": {
|
|
119
|
+
"type": 0,
|
|
120
|
+
"secret": "jwt_secret_key",
|
|
121
|
+
"algorithms": ["HS256"],
|
|
122
|
+
"audience": "my-app"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Tenant-Specific OAuth
|
|
128
|
+
|
|
129
|
+
Tenants can override OAuth settings via `tenantOauth`:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
{
|
|
133
|
+
"type": 0, // Override to JWT
|
|
134
|
+
"secret": "tenant_jwt_secret"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## OAuth Service Integration
|
|
139
|
+
|
|
140
|
+
Default OAuth service configuration:
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
{
|
|
144
|
+
"oauthService": {
|
|
145
|
+
"name": "oauth",
|
|
146
|
+
"tokenApi": "/token",
|
|
147
|
+
"authorizationApi": "/authorization",
|
|
148
|
+
"pinApi": "/pin"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Error Codes
|
|
154
|
+
|
|
155
|
+
| Code | Description |
|
|
156
|
+
|------|-------------|
|
|
157
|
+
| 143 | Invalid or missing JWT token |
|
|
158
|
+
| OAuth2Error | Various OAuth2 errors (invalid_token, expired, etc.) |
|
|
159
|
+
|
|
160
|
+
## Properties Set
|
|
161
|
+
|
|
162
|
+
| Property | Type | Description |
|
|
163
|
+
|----------|------|-------------|
|
|
164
|
+
| `req.oauth.bearerToken` | object | Decoded token or user object |
|
|
165
|
+
| `req.oauth.type` | number | OAuth type (0=JWT, 2=OAuth2) |
|
|
166
|
+
|
|
167
|
+
## Usage Notes
|
|
168
|
+
|
|
169
|
+
- OAuth type can be set globally or per-tenant
|
|
170
|
+
- JWT requires `Authorization: Bearer <token>` header
|
|
171
|
+
- OAuth2 uses `access_token` query parameter or header
|
|
172
|
+
- Tenant OAuth settings override global settings
|
|
173
|
+
- OAuth model is provided by configuration (provision module)
|