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.
- package/README.md +56 -15
- package/dist/s3db.cjs +72446 -39022
- package/dist/s3db.cjs.map +1 -1
- package/dist/s3db.es.js +72172 -38790
- package/dist/s3db.es.js.map +1 -1
- package/mcp/lib/base-handler.js +157 -0
- package/mcp/lib/handlers/connection-handler.js +280 -0
- package/mcp/lib/handlers/query-handler.js +533 -0
- package/mcp/lib/handlers/resource-handler.js +428 -0
- package/mcp/lib/tool-registry.js +336 -0
- package/mcp/lib/tools/connection-tools.js +161 -0
- package/mcp/lib/tools/query-tools.js +267 -0
- package/mcp/lib/tools/resource-tools.js +404 -0
- package/package.json +85 -50
- package/src/clients/memory-client.class.js +346 -191
- package/src/clients/memory-storage.class.js +300 -84
- package/src/clients/s3-client.class.js +7 -6
- package/src/concerns/geo-encoding.js +19 -2
- package/src/concerns/ip.js +59 -9
- package/src/concerns/money.js +8 -1
- package/src/concerns/password-hashing.js +49 -8
- package/src/concerns/plugin-storage.js +186 -18
- package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
- package/src/database.class.js +139 -29
- package/src/errors.js +332 -42
- package/src/plugins/api/auth/oidc-auth.js +66 -17
- package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
- package/src/plugins/api/auth/strategies/factory.class.js +63 -0
- package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
- package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
- package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
- package/src/plugins/api/concerns/failban-manager.js +106 -57
- package/src/plugins/api/concerns/route-context.js +601 -0
- package/src/plugins/api/index.js +168 -40
- package/src/plugins/api/routes/auth-routes.js +198 -30
- package/src/plugins/api/routes/resource-routes.js +19 -4
- package/src/plugins/api/server/health-manager.class.js +163 -0
- package/src/plugins/api/server/middleware-chain.class.js +310 -0
- package/src/plugins/api/server/router.class.js +472 -0
- package/src/plugins/api/server.js +280 -1303
- package/src/plugins/api/utils/custom-routes.js +17 -5
- package/src/plugins/api/utils/guards.js +76 -17
- package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
- package/src/plugins/api/utils/openapi-generator.js +7 -6
- package/src/plugins/audit.plugin.js +30 -8
- package/src/plugins/backup.plugin.js +110 -14
- package/src/plugins/cache/cache.class.js +22 -5
- package/src/plugins/cache/filesystem-cache.class.js +116 -19
- package/src/plugins/cache/memory-cache.class.js +211 -57
- package/src/plugins/cache/multi-tier-cache.class.js +371 -0
- package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
- package/src/plugins/cache/redis-cache.class.js +552 -0
- package/src/plugins/cache/s3-cache.class.js +17 -8
- package/src/plugins/cache.plugin.js +176 -61
- package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
- package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
- package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
- package/src/plugins/cloud-inventory/index.js +29 -8
- package/src/plugins/cloud-inventory/registry.js +64 -42
- package/src/plugins/cloud-inventory.plugin.js +240 -138
- package/src/plugins/concerns/plugin-dependencies.js +54 -0
- package/src/plugins/concerns/resource-names.js +100 -0
- package/src/plugins/consumers/index.js +10 -2
- package/src/plugins/consumers/sqs-consumer.js +12 -2
- package/src/plugins/cookie-farm-suite.plugin.js +278 -0
- package/src/plugins/cookie-farm.errors.js +73 -0
- package/src/plugins/cookie-farm.plugin.js +869 -0
- package/src/plugins/costs.plugin.js +7 -1
- package/src/plugins/eventual-consistency/analytics.js +94 -19
- package/src/plugins/eventual-consistency/config.js +15 -7
- package/src/plugins/eventual-consistency/consolidation.js +29 -11
- package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
- package/src/plugins/eventual-consistency/helpers.js +39 -14
- package/src/plugins/eventual-consistency/install.js +21 -2
- package/src/plugins/eventual-consistency/utils.js +32 -10
- package/src/plugins/fulltext.plugin.js +38 -11
- package/src/plugins/geo.plugin.js +61 -9
- package/src/plugins/identity/concerns/config.js +61 -0
- package/src/plugins/identity/concerns/mfa-manager.js +15 -2
- package/src/plugins/identity/concerns/rate-limit.js +124 -0
- package/src/plugins/identity/concerns/resource-schemas.js +9 -1
- package/src/plugins/identity/concerns/token-generator.js +29 -4
- package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
- package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
- package/src/plugins/identity/drivers/index.js +18 -0
- package/src/plugins/identity/drivers/password-driver.js +122 -0
- package/src/plugins/identity/email-service.js +17 -2
- package/src/plugins/identity/index.js +413 -69
- package/src/plugins/identity/oauth2-server.js +413 -30
- package/src/plugins/identity/oidc-discovery.js +16 -8
- package/src/plugins/identity/rsa-keys.js +115 -35
- package/src/plugins/identity/server.js +166 -45
- package/src/plugins/identity/session-manager.js +53 -7
- package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
- package/src/plugins/identity/ui/routes.js +363 -255
- package/src/plugins/importer/index.js +153 -20
- package/src/plugins/index.js +9 -2
- package/src/plugins/kubernetes-inventory/index.js +6 -0
- package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
- package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
- package/src/plugins/kubernetes-inventory.plugin.js +980 -0
- package/src/plugins/metrics.plugin.js +64 -16
- package/src/plugins/ml/base-model.class.js +25 -15
- package/src/plugins/ml/regression-model.class.js +1 -1
- package/src/plugins/ml.errors.js +57 -25
- package/src/plugins/ml.plugin.js +28 -4
- package/src/plugins/namespace.js +210 -0
- package/src/plugins/plugin.class.js +180 -8
- package/src/plugins/puppeteer/console-monitor.js +729 -0
- package/src/plugins/puppeteer/cookie-manager.js +492 -0
- package/src/plugins/puppeteer/network-monitor.js +816 -0
- package/src/plugins/puppeteer/performance-manager.js +746 -0
- package/src/plugins/puppeteer/proxy-manager.js +478 -0
- package/src/plugins/puppeteer/stealth-manager.js +556 -0
- package/src/plugins/puppeteer.errors.js +81 -0
- package/src/plugins/puppeteer.plugin.js +1327 -0
- package/src/plugins/queue-consumer.plugin.js +69 -14
- package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
- package/src/plugins/recon/concerns/command-runner.js +148 -0
- package/src/plugins/recon/concerns/diff-detector.js +372 -0
- package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
- package/src/plugins/recon/concerns/process-manager.js +338 -0
- package/src/plugins/recon/concerns/report-generator.js +478 -0
- package/src/plugins/recon/concerns/security-analyzer.js +571 -0
- package/src/plugins/recon/concerns/target-normalizer.js +68 -0
- package/src/plugins/recon/config/defaults.js +321 -0
- package/src/plugins/recon/config/resources.js +370 -0
- package/src/plugins/recon/index.js +778 -0
- package/src/plugins/recon/managers/dependency-manager.js +174 -0
- package/src/plugins/recon/managers/scheduler-manager.js +179 -0
- package/src/plugins/recon/managers/storage-manager.js +745 -0
- package/src/plugins/recon/managers/target-manager.js +274 -0
- package/src/plugins/recon/stages/asn-stage.js +314 -0
- package/src/plugins/recon/stages/certificate-stage.js +84 -0
- package/src/plugins/recon/stages/dns-stage.js +107 -0
- package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
- package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
- package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
- package/src/plugins/recon/stages/http-stage.js +89 -0
- package/src/plugins/recon/stages/latency-stage.js +148 -0
- package/src/plugins/recon/stages/massdns-stage.js +302 -0
- package/src/plugins/recon/stages/osint-stage.js +1373 -0
- package/src/plugins/recon/stages/ports-stage.js +169 -0
- package/src/plugins/recon/stages/screenshot-stage.js +94 -0
- package/src/plugins/recon/stages/secrets-stage.js +514 -0
- package/src/plugins/recon/stages/subdomains-stage.js +295 -0
- package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
- package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
- package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
- package/src/plugins/recon/stages/whois-stage.js +349 -0
- package/src/plugins/recon.plugin.js +75 -0
- package/src/plugins/recon.plugin.js.backup +2635 -0
- package/src/plugins/relation.errors.js +87 -14
- package/src/plugins/replicator.plugin.js +514 -137
- package/src/plugins/replicators/base-replicator.class.js +89 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
- package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mysql-replicator.class.js +52 -17
- package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
- package/src/plugins/replicators/postgres-replicator.class.js +62 -27
- package/src/plugins/replicators/s3db-replicator.class.js +25 -18
- package/src/plugins/replicators/schema-sync.helper.js +3 -3
- package/src/plugins/replicators/sqs-replicator.class.js +8 -2
- package/src/plugins/replicators/turso-replicator.class.js +23 -3
- package/src/plugins/replicators/webhook-replicator.class.js +42 -4
- package/src/plugins/s3-queue.plugin.js +464 -65
- package/src/plugins/scheduler.plugin.js +20 -6
- package/src/plugins/state-machine.plugin.js +40 -9
- package/src/plugins/tfstate/base-driver.js +28 -4
- package/src/plugins/tfstate/errors.js +65 -10
- package/src/plugins/tfstate/filesystem-driver.js +52 -8
- package/src/plugins/tfstate/index.js +163 -90
- package/src/plugins/tfstate/s3-driver.js +64 -6
- package/src/plugins/ttl.plugin.js +72 -17
- package/src/plugins/vector/distances.js +18 -12
- package/src/plugins/vector/kmeans.js +26 -4
- package/src/resource.class.js +115 -19
- package/src/testing/factory.class.js +20 -3
- package/src/testing/seeder.class.js +7 -1
- package/src/clients/memory-client.md +0 -917
- 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
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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:
|
|
186
|
-
email: claims.email ||
|
|
187
|
-
username: claims.preferred_username || claims.email ||
|
|
188
|
-
name: claims.name || claims.email ||
|
|
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 (
|
|
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
|
+
}
|