soajs.controller 4.2.41 → 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.
Files changed (42) hide show
  1. package/.github/workflows/ci.yml +43 -0
  2. package/.github/workflows/release.yml +92 -0
  3. package/ARCHITECTURE.md +193 -0
  4. package/Gruntfile.js +1 -1
  5. package/docs/configuration-custom-registry.md +421 -0
  6. package/docs/configuration-services-config.md +275 -0
  7. package/docs/data-flow.md +138 -0
  8. package/docs/deployment.md +205 -0
  9. package/docs/external-integrations.md +159 -0
  10. package/docs/gateway-routes.md +259 -0
  11. package/docs/maintenance-routes.md +308 -0
  12. package/docs/middleware/awareness.md +120 -0
  13. package/docs/middleware/cors.md +88 -0
  14. package/docs/middleware/enhancer.md +75 -0
  15. package/docs/middleware/favicon.md +36 -0
  16. package/docs/middleware/gotoService.md +146 -0
  17. package/docs/middleware/ip2ban.md +70 -0
  18. package/docs/middleware/key.md +196 -0
  19. package/docs/middleware/keyACL.md +139 -0
  20. package/docs/middleware/lastSeen.md +111 -0
  21. package/docs/middleware/maintenanceMode.md +81 -0
  22. package/docs/middleware/mt.md +188 -0
  23. package/docs/middleware/oauth.md +173 -0
  24. package/docs/middleware/response.md +106 -0
  25. package/docs/middleware/soajs.md +71 -0
  26. package/docs/middleware/traffic.md +190 -0
  27. package/docs/middleware/url.md +102 -0
  28. package/docs/multi-tenant-security.md +183 -0
  29. package/docs/request-flow.md +230 -0
  30. package/docs/service-discovery.md +167 -0
  31. package/mw/gotoService/redirectToService.js +15 -4
  32. package/mw/key/index.js +16 -1
  33. package/mw/lastSeen/index.js +3 -0
  34. package/mw/mt/urac.js +21 -1
  35. package/mw/mt/utils.js +2 -0
  36. package/package.json +7 -7
  37. package/test/integration/UC1-gateway-routes/index.js +2 -2
  38. package/test/unit/mw/key/index.js +150 -0
  39. package/test/unit/mw/lastSeen/index.js +5 -4
  40. package/test/unit/mw/mt/urac.js +157 -4
  41. package/test/unit/mw/mt/utils.js +6 -6
  42. 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)