s3db.js 13.6.1 → 14.0.2

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 (189) hide show
  1. package/README.md +56 -15
  2. package/dist/s3db.cjs +72446 -39022
  3. package/dist/s3db.cjs.map +1 -1
  4. package/dist/s3db.es.js +72172 -38790
  5. package/dist/s3db.es.js.map +1 -1
  6. package/mcp/lib/base-handler.js +157 -0
  7. package/mcp/lib/handlers/connection-handler.js +280 -0
  8. package/mcp/lib/handlers/query-handler.js +533 -0
  9. package/mcp/lib/handlers/resource-handler.js +428 -0
  10. package/mcp/lib/tool-registry.js +336 -0
  11. package/mcp/lib/tools/connection-tools.js +161 -0
  12. package/mcp/lib/tools/query-tools.js +267 -0
  13. package/mcp/lib/tools/resource-tools.js +404 -0
  14. package/package.json +85 -50
  15. package/src/clients/memory-client.class.js +346 -191
  16. package/src/clients/memory-storage.class.js +300 -84
  17. package/src/clients/s3-client.class.js +7 -6
  18. package/src/concerns/geo-encoding.js +19 -2
  19. package/src/concerns/ip.js +59 -9
  20. package/src/concerns/money.js +8 -1
  21. package/src/concerns/password-hashing.js +49 -8
  22. package/src/concerns/plugin-storage.js +186 -18
  23. package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
  24. package/src/database.class.js +139 -29
  25. package/src/errors.js +332 -42
  26. package/src/plugins/api/auth/oidc-auth.js +66 -17
  27. package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
  28. package/src/plugins/api/auth/strategies/factory.class.js +63 -0
  29. package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
  30. package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
  31. package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
  32. package/src/plugins/api/concerns/failban-manager.js +106 -57
  33. package/src/plugins/api/concerns/route-context.js +601 -0
  34. package/src/plugins/api/index.js +168 -40
  35. package/src/plugins/api/routes/auth-routes.js +198 -30
  36. package/src/plugins/api/routes/resource-routes.js +19 -4
  37. package/src/plugins/api/server/health-manager.class.js +163 -0
  38. package/src/plugins/api/server/middleware-chain.class.js +310 -0
  39. package/src/plugins/api/server/router.class.js +472 -0
  40. package/src/plugins/api/server.js +280 -1303
  41. package/src/plugins/api/utils/custom-routes.js +17 -5
  42. package/src/plugins/api/utils/guards.js +76 -17
  43. package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
  44. package/src/plugins/api/utils/openapi-generator.js +7 -6
  45. package/src/plugins/audit.plugin.js +30 -8
  46. package/src/plugins/backup.plugin.js +110 -14
  47. package/src/plugins/cache/cache.class.js +22 -5
  48. package/src/plugins/cache/filesystem-cache.class.js +116 -19
  49. package/src/plugins/cache/memory-cache.class.js +211 -57
  50. package/src/plugins/cache/multi-tier-cache.class.js +371 -0
  51. package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
  52. package/src/plugins/cache/redis-cache.class.js +552 -0
  53. package/src/plugins/cache/s3-cache.class.js +17 -8
  54. package/src/plugins/cache.plugin.js +176 -61
  55. package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
  56. package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
  57. package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
  58. package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
  59. package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
  60. package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
  61. package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
  62. package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
  63. package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
  64. package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
  65. package/src/plugins/cloud-inventory/index.js +29 -8
  66. package/src/plugins/cloud-inventory/registry.js +64 -42
  67. package/src/plugins/cloud-inventory.plugin.js +240 -138
  68. package/src/plugins/concerns/plugin-dependencies.js +54 -0
  69. package/src/plugins/concerns/resource-names.js +100 -0
  70. package/src/plugins/consumers/index.js +10 -2
  71. package/src/plugins/consumers/sqs-consumer.js +12 -2
  72. package/src/plugins/cookie-farm-suite.plugin.js +278 -0
  73. package/src/plugins/cookie-farm.errors.js +73 -0
  74. package/src/plugins/cookie-farm.plugin.js +869 -0
  75. package/src/plugins/costs.plugin.js +7 -1
  76. package/src/plugins/eventual-consistency/analytics.js +94 -19
  77. package/src/plugins/eventual-consistency/config.js +15 -7
  78. package/src/plugins/eventual-consistency/consolidation.js +29 -11
  79. package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
  80. package/src/plugins/eventual-consistency/helpers.js +39 -14
  81. package/src/plugins/eventual-consistency/install.js +21 -2
  82. package/src/plugins/eventual-consistency/utils.js +32 -10
  83. package/src/plugins/fulltext.plugin.js +38 -11
  84. package/src/plugins/geo.plugin.js +61 -9
  85. package/src/plugins/identity/concerns/config.js +61 -0
  86. package/src/plugins/identity/concerns/mfa-manager.js +15 -2
  87. package/src/plugins/identity/concerns/rate-limit.js +124 -0
  88. package/src/plugins/identity/concerns/resource-schemas.js +9 -1
  89. package/src/plugins/identity/concerns/token-generator.js +29 -4
  90. package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
  91. package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
  92. package/src/plugins/identity/drivers/index.js +18 -0
  93. package/src/plugins/identity/drivers/password-driver.js +122 -0
  94. package/src/plugins/identity/email-service.js +17 -2
  95. package/src/plugins/identity/index.js +413 -69
  96. package/src/plugins/identity/oauth2-server.js +413 -30
  97. package/src/plugins/identity/oidc-discovery.js +16 -8
  98. package/src/plugins/identity/rsa-keys.js +115 -35
  99. package/src/plugins/identity/server.js +166 -45
  100. package/src/plugins/identity/session-manager.js +53 -7
  101. package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
  102. package/src/plugins/identity/ui/routes.js +363 -255
  103. package/src/plugins/importer/index.js +153 -20
  104. package/src/plugins/index.js +9 -2
  105. package/src/plugins/kubernetes-inventory/index.js +6 -0
  106. package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
  107. package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
  108. package/src/plugins/kubernetes-inventory.plugin.js +980 -0
  109. package/src/plugins/metrics.plugin.js +64 -16
  110. package/src/plugins/ml/base-model.class.js +25 -15
  111. package/src/plugins/ml/regression-model.class.js +1 -1
  112. package/src/plugins/ml.errors.js +57 -25
  113. package/src/plugins/ml.plugin.js +28 -4
  114. package/src/plugins/namespace.js +210 -0
  115. package/src/plugins/plugin.class.js +180 -8
  116. package/src/plugins/puppeteer/console-monitor.js +729 -0
  117. package/src/plugins/puppeteer/cookie-manager.js +492 -0
  118. package/src/plugins/puppeteer/network-monitor.js +816 -0
  119. package/src/plugins/puppeteer/performance-manager.js +746 -0
  120. package/src/plugins/puppeteer/proxy-manager.js +478 -0
  121. package/src/plugins/puppeteer/stealth-manager.js +556 -0
  122. package/src/plugins/puppeteer.errors.js +81 -0
  123. package/src/plugins/puppeteer.plugin.js +1327 -0
  124. package/src/plugins/queue-consumer.plugin.js +69 -14
  125. package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
  126. package/src/plugins/recon/concerns/command-runner.js +148 -0
  127. package/src/plugins/recon/concerns/diff-detector.js +372 -0
  128. package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
  129. package/src/plugins/recon/concerns/process-manager.js +338 -0
  130. package/src/plugins/recon/concerns/report-generator.js +478 -0
  131. package/src/plugins/recon/concerns/security-analyzer.js +571 -0
  132. package/src/plugins/recon/concerns/target-normalizer.js +68 -0
  133. package/src/plugins/recon/config/defaults.js +321 -0
  134. package/src/plugins/recon/config/resources.js +370 -0
  135. package/src/plugins/recon/index.js +778 -0
  136. package/src/plugins/recon/managers/dependency-manager.js +174 -0
  137. package/src/plugins/recon/managers/scheduler-manager.js +179 -0
  138. package/src/plugins/recon/managers/storage-manager.js +745 -0
  139. package/src/plugins/recon/managers/target-manager.js +274 -0
  140. package/src/plugins/recon/stages/asn-stage.js +314 -0
  141. package/src/plugins/recon/stages/certificate-stage.js +84 -0
  142. package/src/plugins/recon/stages/dns-stage.js +107 -0
  143. package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
  144. package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
  145. package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
  146. package/src/plugins/recon/stages/http-stage.js +89 -0
  147. package/src/plugins/recon/stages/latency-stage.js +148 -0
  148. package/src/plugins/recon/stages/massdns-stage.js +302 -0
  149. package/src/plugins/recon/stages/osint-stage.js +1373 -0
  150. package/src/plugins/recon/stages/ports-stage.js +169 -0
  151. package/src/plugins/recon/stages/screenshot-stage.js +94 -0
  152. package/src/plugins/recon/stages/secrets-stage.js +514 -0
  153. package/src/plugins/recon/stages/subdomains-stage.js +295 -0
  154. package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
  155. package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
  156. package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
  157. package/src/plugins/recon/stages/whois-stage.js +349 -0
  158. package/src/plugins/recon.plugin.js +75 -0
  159. package/src/plugins/recon.plugin.js.backup +2635 -0
  160. package/src/plugins/relation.errors.js +87 -14
  161. package/src/plugins/replicator.plugin.js +514 -137
  162. package/src/plugins/replicators/base-replicator.class.js +89 -1
  163. package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
  164. package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
  165. package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
  166. package/src/plugins/replicators/mysql-replicator.class.js +52 -17
  167. package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
  168. package/src/plugins/replicators/postgres-replicator.class.js +62 -27
  169. package/src/plugins/replicators/s3db-replicator.class.js +25 -18
  170. package/src/plugins/replicators/schema-sync.helper.js +3 -3
  171. package/src/plugins/replicators/sqs-replicator.class.js +8 -2
  172. package/src/plugins/replicators/turso-replicator.class.js +23 -3
  173. package/src/plugins/replicators/webhook-replicator.class.js +42 -4
  174. package/src/plugins/s3-queue.plugin.js +464 -65
  175. package/src/plugins/scheduler.plugin.js +20 -6
  176. package/src/plugins/state-machine.plugin.js +40 -9
  177. package/src/plugins/tfstate/base-driver.js +28 -4
  178. package/src/plugins/tfstate/errors.js +65 -10
  179. package/src/plugins/tfstate/filesystem-driver.js +52 -8
  180. package/src/plugins/tfstate/index.js +163 -90
  181. package/src/plugins/tfstate/s3-driver.js +64 -6
  182. package/src/plugins/ttl.plugin.js +72 -17
  183. package/src/plugins/vector/distances.js +18 -12
  184. package/src/plugins/vector/kmeans.js +26 -4
  185. package/src/resource.class.js +115 -19
  186. package/src/testing/factory.class.js +20 -3
  187. package/src/testing/seeder.class.js +7 -1
  188. package/src/clients/memory-client.md +0 -917
  189. package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
@@ -107,20 +107,49 @@ export function validateOidcConfig(config) {
107
107
  * @returns {Promise<{user: Object, created: boolean}>} User object and creation status
108
108
  */
109
109
  async function getOrCreateUser(usersResource, claims, config) {
110
- const userId = claims.email || claims.preferred_username || claims.sub;
111
-
112
- if (!userId) {
113
- throw new Error('Cannot extract user ID from OIDC claims (no email/preferred_username/sub)');
110
+ const {
111
+ autoCreateUser = true,
112
+ userIdClaim = 'sub',
113
+ fallbackIdClaims = ['email', 'preferred_username'],
114
+ lookupFields = ['email', 'preferred_username']
115
+ } = config;
116
+
117
+ const candidateIds = [];
118
+ if (userIdClaim && claims[userIdClaim]) {
119
+ candidateIds.push(String(claims[userIdClaim]));
120
+ }
121
+ for (const field of fallbackIdClaims) {
122
+ if (!field || field === userIdClaim) continue;
123
+ const value = claims[field];
124
+ if (value) {
125
+ candidateIds.push(String(value));
126
+ }
114
127
  }
115
128
 
116
- // Try to get existing user
117
129
  let user = null;
118
- let userExists = false;
119
- try {
120
- user = await usersResource.get(userId);
121
- userExists = true;
122
- } catch (err) {
123
- // User not found, will create below
130
+ // Try direct lookups by id
131
+ for (const candidate of candidateIds) {
132
+ try {
133
+ user = await usersResource.get(candidate);
134
+ break;
135
+ } catch (_) {
136
+ // Not found, continue with next candidate
137
+ }
138
+ }
139
+
140
+ // Fallback: query by lookup fields
141
+ if (!user) {
142
+ const fields = Array.isArray(lookupFields) ? lookupFields : [lookupFields];
143
+ for (const field of fields) {
144
+ if (!field) continue;
145
+ const value = claims[field];
146
+ if (!value) continue;
147
+ const results = await usersResource.query({ [field]: value }, { limit: 1 });
148
+ if (results.length > 0) {
149
+ user = results[0];
150
+ break;
151
+ }
152
+ }
124
153
  }
125
154
 
126
155
  const now = new Date().toISOString();
@@ -180,12 +209,22 @@ async function getOrCreateUser(usersResource, claims, config) {
180
209
  return { user, created: false };
181
210
  }
182
211
 
183
- // Create new user
212
+ if (!autoCreateUser) {
213
+ return { user: null, created: false };
214
+ }
215
+
216
+ // Determine ID for new user
217
+ const newUserId = candidateIds[0];
218
+
219
+ if (!newUserId) {
220
+ throw new Error('Cannot determine user ID from OIDC claims');
221
+ }
222
+
184
223
  const newUser = {
185
- id: userId,
186
- email: claims.email || userId,
187
- username: claims.preferred_username || claims.email || userId,
188
- name: claims.name || claims.email || userId,
224
+ id: newUserId,
225
+ email: claims.email || newUserId,
226
+ username: claims.preferred_username || claims.email || newUserId,
227
+ name: claims.name || claims.email || newUserId,
189
228
  picture: claims.picture || null,
190
229
  role: config.defaultRole || 'user',
191
230
  scopes: config.defaultScopes || ['openid', 'profile', 'email'],
@@ -279,6 +318,9 @@ export function createOIDCHandler(config, app, usersResource, events = null) {
279
318
  postLogoutRedirect: '/',
280
319
  idpLogout: true,
281
320
  autoCreateUser: true,
321
+ userIdClaim: 'sub',
322
+ fallbackIdClaims: ['email', 'preferred_username'],
323
+ lookupFields: ['email', 'preferred_username'],
282
324
  autoRefreshTokens: true,
283
325
  refreshThreshold: 300000, // 5 minutes before expiry
284
326
  cookieSecure: process.env.NODE_ENV === 'production',
@@ -477,12 +519,19 @@ export function createOIDCHandler(config, app, usersResource, events = null) {
477
519
  // Auto-create/update user
478
520
  let user = null;
479
521
  let userCreated = false;
480
- if (autoCreateUser && usersResource) {
522
+ if (usersResource) {
481
523
  try {
482
524
  const result = await getOrCreateUser(usersResource, idTokenClaims, finalConfig);
483
525
  user = result.user;
484
526
  userCreated = result.created;
485
527
 
528
+ if (!user) {
529
+ return c.json({
530
+ error: 'User not provisioned',
531
+ message: 'User does not exist in configured auth resource'
532
+ }, 403);
533
+ }
534
+
486
535
  // Emit user events
487
536
  if (events) {
488
537
  if (userCreated) {
@@ -0,0 +1,74 @@
1
+ /**
2
+ * BaseAuthStrategy - Abstract base for auth strategies
3
+ *
4
+ * All auth strategies extend this class and implement createMiddleware()
5
+ */
6
+
7
+ export class BaseAuthStrategy {
8
+ constructor({ drivers, authResource, oidcMiddleware, verbose }) {
9
+ this.drivers = drivers || [];
10
+ this.authResource = authResource;
11
+ this.oidcMiddleware = oidcMiddleware;
12
+ this.verbose = verbose;
13
+ }
14
+
15
+ /**
16
+ * Extract driver configs from drivers array
17
+ * @param {Array<string>} driverNames - Names of drivers to extract
18
+ * @returns {Object} Driver configs
19
+ * @protected
20
+ */
21
+ extractDriverConfigs(driverNames) {
22
+ const configs = {
23
+ jwt: {},
24
+ apiKey: {},
25
+ basic: {},
26
+ oauth2: {}
27
+ };
28
+
29
+ for (const driverDef of this.drivers) {
30
+ const driverName = driverDef.driver;
31
+ const driverConfig = driverDef.config || {};
32
+
33
+ // Skip if not in requested drivers
34
+ if (driverNames && !driverNames.includes(driverName)) {
35
+ continue;
36
+ }
37
+
38
+ // Skip oauth2-server and oidc drivers (handled separately)
39
+ if (driverName === 'oauth2-server' || driverName === 'oidc') {
40
+ continue;
41
+ }
42
+
43
+ // Map driver configs
44
+ if (driverName === 'jwt') {
45
+ configs.jwt = {
46
+ secret: driverConfig.jwtSecret || driverConfig.secret,
47
+ expiresIn: driverConfig.jwtExpiresIn || driverConfig.expiresIn || '7d'
48
+ };
49
+ } else if (driverName === 'apiKey') {
50
+ configs.apiKey = {
51
+ headerName: driverConfig.headerName || 'X-API-Key'
52
+ };
53
+ } else if (driverName === 'basic') {
54
+ configs.basic = {
55
+ realm: driverConfig.realm || 'API Access',
56
+ passphrase: driverConfig.passphrase || 'secret'
57
+ };
58
+ } else if (driverName === 'oauth2') {
59
+ configs.oauth2 = driverConfig;
60
+ }
61
+ }
62
+
63
+ return configs;
64
+ }
65
+
66
+ /**
67
+ * Create auth middleware (must be implemented by subclasses)
68
+ * @abstract
69
+ * @returns {Function} Hono middleware
70
+ */
71
+ createMiddleware() {
72
+ throw new Error('createMiddleware() must be implemented by subclass');
73
+ }
74
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * AuthStrategyFactory - Creates appropriate auth strategy based on config
3
+ *
4
+ * Strategy selection priority:
5
+ * 1. PathRulesStrategy - if pathRules is defined (modern, recommended)
6
+ * 2. PathBasedStrategy - if pathAuth is defined (legacy)
7
+ * 3. GlobalAuthStrategy - default (all drivers, optional auth)
8
+ *
9
+ * @example
10
+ * const strategy = AuthStrategyFactory.create(config);
11
+ * const middleware = strategy.createMiddleware();
12
+ */
13
+
14
+ import { GlobalAuthStrategy } from './global-strategy.class.js';
15
+ import { PathBasedAuthStrategy } from './path-based-strategy.class.js';
16
+ import { PathRulesAuthStrategy } from './path-rules-strategy.class.js';
17
+
18
+ export class AuthStrategyFactory {
19
+ /**
20
+ * Create appropriate auth strategy based on config
21
+ * @param {Object} config - Auth configuration
22
+ * @param {Array} config.drivers - Auth driver configurations
23
+ * @param {Object} config.authResource - Users resource for authentication
24
+ * @param {Function} config.oidcMiddleware - OIDC middleware (if configured)
25
+ * @param {Array} [config.pathRules] - Modern path rules (priority 1)
26
+ * @param {Object} [config.pathAuth] - Legacy path auth config (priority 2)
27
+ * @param {Object} [config.events] - Event emitter
28
+ * @param {boolean} [config.verbose] - Enable verbose logging
29
+ * @returns {BaseAuthStrategy} Auth strategy instance
30
+ */
31
+ static create({ drivers, authResource, oidcMiddleware, pathRules, pathAuth, events, verbose }) {
32
+ // Priority 1: PathRules (modern API)
33
+ if (pathRules && pathRules.length > 0) {
34
+ return new PathRulesAuthStrategy({
35
+ drivers,
36
+ authResource,
37
+ oidcMiddleware,
38
+ pathRules,
39
+ events,
40
+ verbose
41
+ });
42
+ }
43
+
44
+ // Priority 2: PathAuth (legacy)
45
+ if (pathAuth) {
46
+ return new PathBasedAuthStrategy({
47
+ drivers,
48
+ authResource,
49
+ oidcMiddleware,
50
+ pathAuth,
51
+ verbose
52
+ });
53
+ }
54
+
55
+ // Priority 3: Global (default)
56
+ return new GlobalAuthStrategy({
57
+ drivers,
58
+ authResource,
59
+ oidcMiddleware,
60
+ verbose
61
+ });
62
+ }
63
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * GlobalAuthStrategy - Global authentication for all routes
3
+ *
4
+ * Uses all configured auth drivers with optional=true
5
+ * (guards control actual authorization)
6
+ */
7
+
8
+ import { BaseAuthStrategy } from './base-strategy.class.js';
9
+ import { createAuthMiddleware } from '../index.js';
10
+
11
+ export class GlobalAuthStrategy extends BaseAuthStrategy {
12
+ createMiddleware() {
13
+ const methods = [];
14
+ const driverConfigs = this.extractDriverConfigs(null); // all drivers
15
+
16
+ for (const driverDef of this.drivers) {
17
+ const driverName = driverDef.driver;
18
+
19
+ // Skip oauth2-server and oidc
20
+ if (driverName === 'oauth2-server' || driverName === 'oidc') {
21
+ continue;
22
+ }
23
+
24
+ if (!methods.includes(driverName)) {
25
+ methods.push(driverName);
26
+ }
27
+ }
28
+
29
+ if (this.verbose) {
30
+ console.log(`[GlobalAuthStrategy] Using global auth with methods: ${methods.join(', ')}`);
31
+ }
32
+
33
+ return createAuthMiddleware({
34
+ methods,
35
+ jwt: driverConfigs.jwt,
36
+ apiKey: driverConfigs.apiKey,
37
+ basic: driverConfigs.basic,
38
+ oauth2: driverConfigs.oauth2,
39
+ oidc: this.oidcMiddleware || null,
40
+ usersResource: this.authResource,
41
+ optional: true // Let guards handle authorization
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * PathBasedAuthStrategy - Path-based authentication using pathAuth config
3
+ *
4
+ * Legacy path-based auth system (before pathRules was introduced)
5
+ * Matches request path against pathAuth patterns
6
+ */
7
+
8
+ import { BaseAuthStrategy } from './base-strategy.class.js';
9
+ import { createAuthMiddleware } from '../index.js';
10
+ import { findBestMatch } from '../../utils/path-matcher.js';
11
+
12
+ export class PathBasedAuthStrategy extends BaseAuthStrategy {
13
+ constructor({ drivers, authResource, oidcMiddleware, pathAuth, verbose }) {
14
+ super({ drivers, authResource, oidcMiddleware, verbose });
15
+ this.pathAuth = pathAuth;
16
+ }
17
+
18
+ createMiddleware() {
19
+ if (this.verbose) {
20
+ console.log('[PathBasedAuthStrategy] Using legacy pathAuth system');
21
+ }
22
+
23
+ return async (c, next) => {
24
+ const requestPath = c.req.path;
25
+
26
+ // Find best matching rule
27
+ const matchedRule = findBestMatch(this.pathAuth, requestPath);
28
+
29
+ if (this.verbose) {
30
+ if (matchedRule) {
31
+ console.log(`[PathBasedAuthStrategy] Path ${requestPath} matched rule: ${matchedRule.pattern}`);
32
+ } else {
33
+ console.log(`[PathBasedAuthStrategy] Path ${requestPath} no pathAuth rule matched (using global auth)`);
34
+ }
35
+ }
36
+
37
+ // No rule matched - use global auth (all drivers, optional)
38
+ if (!matchedRule) {
39
+ const methods = this.drivers
40
+ .map(d => d.driver)
41
+ .filter(d => d !== 'oauth2-server' && d !== 'oidc');
42
+
43
+ const driverConfigs = this.extractDriverConfigs(null);
44
+
45
+ const globalAuth = createAuthMiddleware({
46
+ methods,
47
+ jwt: driverConfigs.jwt,
48
+ apiKey: driverConfigs.apiKey,
49
+ basic: driverConfigs.basic,
50
+ oauth2: driverConfigs.oauth2,
51
+ oidc: this.oidcMiddleware || null,
52
+ usersResource: this.authResource,
53
+ optional: true
54
+ });
55
+
56
+ return await globalAuth(c, next);
57
+ }
58
+
59
+ // Rule matched - check if auth is required
60
+ if (!matchedRule.required) {
61
+ // Public path - no auth required
62
+ return await next();
63
+ }
64
+
65
+ // Auth required - apply with specific drivers from rule
66
+ const ruleMethods = matchedRule.drivers || [];
67
+ const driverConfigs = this.extractDriverConfigs(ruleMethods);
68
+
69
+ const ruleAuth = createAuthMiddleware({
70
+ methods: ruleMethods,
71
+ jwt: driverConfigs.jwt,
72
+ apiKey: driverConfigs.apiKey,
73
+ basic: driverConfigs.basic,
74
+ oauth2: driverConfigs.oauth2,
75
+ oidc: this.oidcMiddleware || null,
76
+ usersResource: this.authResource,
77
+ optional: false // Auth is required
78
+ });
79
+
80
+ return await ruleAuth(c, next);
81
+ };
82
+ }
83
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * PathRulesAuthStrategy - Modern path-based auth using pathRules
3
+ *
4
+ * New path-based auth system with cleaner API:
5
+ * - pathRules: [{ path: '/admin/**', methods: ['oidc'], required: true }]
6
+ *
7
+ * More flexible than pathAuth and easier to configure
8
+ */
9
+
10
+ import { BaseAuthStrategy } from './base-strategy.class.js';
11
+ import { createPathBasedAuthMiddleware } from '../path-auth-matcher.js';
12
+ import { jwtAuth } from '../jwt-auth.js';
13
+ import { apiKeyAuth } from '../api-key-auth.js';
14
+ import { basicAuth } from '../basic-auth.js';
15
+ import { createOAuth2Handler } from '../oauth2-auth.js';
16
+
17
+ export class PathRulesAuthStrategy extends BaseAuthStrategy {
18
+ constructor({ drivers, authResource, oidcMiddleware, pathRules, events, verbose }) {
19
+ super({ drivers, authResource, oidcMiddleware, verbose });
20
+ this.pathRules = pathRules;
21
+ this.events = events;
22
+ }
23
+
24
+ createMiddleware() {
25
+ // Build auth middlewares map by driver type
26
+ const authMiddlewares = {};
27
+
28
+ for (const driverDef of this.drivers) {
29
+ const driverType = driverDef.type || driverDef.driver;
30
+ const driverConfig = driverDef.config || driverDef;
31
+
32
+ // Skip oauth2-server
33
+ if (driverType === 'oauth2-server') {
34
+ continue;
35
+ }
36
+
37
+ // OIDC
38
+ if (driverType === 'oidc') {
39
+ if (this.oidcMiddleware) {
40
+ authMiddlewares.oidc = this.oidcMiddleware;
41
+ }
42
+ continue;
43
+ }
44
+
45
+ // JWT
46
+ if (driverType === 'jwt') {
47
+ authMiddlewares.jwt = jwtAuth({
48
+ secret: driverConfig.jwtSecret || driverConfig.secret,
49
+ expiresIn: driverConfig.jwtExpiresIn || driverConfig.expiresIn || '7d',
50
+ usersResource: this.authResource,
51
+ optional: true
52
+ });
53
+ }
54
+
55
+ // API Key
56
+ if (driverType === 'apiKey') {
57
+ authMiddlewares.apiKey = apiKeyAuth({
58
+ headerName: driverConfig.headerName || 'X-API-Key',
59
+ usersResource: this.authResource,
60
+ optional: true
61
+ });
62
+ }
63
+
64
+ // Basic Auth
65
+ if (driverType === 'basic') {
66
+ authMiddlewares.basic = basicAuth({
67
+ authResource: this.authResource,
68
+ usernameField: driverConfig.usernameField || 'email',
69
+ passwordField: driverConfig.passwordField || 'password',
70
+ passphrase: driverConfig.passphrase || 'secret',
71
+ adminUser: driverConfig.adminUser || null,
72
+ optional: true
73
+ });
74
+ }
75
+
76
+ // OAuth2
77
+ if (driverType === 'oauth2') {
78
+ const oauth2Handler = createOAuth2Handler(driverConfig, this.authResource);
79
+ authMiddlewares.oauth2 = async (c, next) => {
80
+ const user = await oauth2Handler(c);
81
+ if (user) {
82
+ c.set('user', user);
83
+ return await next();
84
+ }
85
+ };
86
+ }
87
+ }
88
+
89
+ if (this.verbose) {
90
+ console.log(`[PathRulesAuthStrategy] Path-based auth with ${this.pathRules.length} rules`);
91
+ console.log(`[PathRulesAuthStrategy] Available auth methods: ${Object.keys(authMiddlewares).join(', ')}`);
92
+ }
93
+
94
+ // Create and return path-based auth middleware
95
+ return createPathBasedAuthMiddleware({
96
+ rules: this.pathRules,
97
+ authMiddlewares,
98
+ unauthorizedHandler: (c, message) => {
99
+ // Content negotiation
100
+ const acceptHeader = c.req.header('accept') || '';
101
+ const acceptsHtml = acceptHeader.includes('text/html');
102
+
103
+ if (acceptsHtml) {
104
+ // Redirect to login if OIDC is available
105
+ if (authMiddlewares.oidc) {
106
+ return c.redirect('/auth/login', 302);
107
+ }
108
+ }
109
+
110
+ return c.json({
111
+ error: 'Unauthorized',
112
+ message
113
+ }, 401);
114
+ },
115
+ events: this.events
116
+ });
117
+ }
118
+ }