@forklaunch/core 0.13.1 → 0.13.3
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/lib/http/index.d.mts +79 -58
- package/lib/http/index.d.ts +79 -58
- package/lib/http/index.js +107 -43
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +107 -43
- package/lib/http/index.mjs.map +1 -1
- package/package.json +8 -8
package/lib/http/index.js
CHANGED
@@ -159,22 +159,44 @@ function isTypedHandler(maybeTypedHandler) {
|
|
159
159
|
var import_common2 = require("@forklaunch/common");
|
160
160
|
|
161
161
|
// src/http/discriminateAuthMethod.ts
|
162
|
+
var import_crypto = require("crypto");
|
162
163
|
var import_jose = require("jose");
|
164
|
+
|
165
|
+
// src/http/guards/isBasicAuthMethod.ts
|
166
|
+
function isBasicAuthMethod(maybeBasicAuthMethod) {
|
167
|
+
return typeof maybeBasicAuthMethod === "object" && maybeBasicAuthMethod !== null && "basic" in maybeBasicAuthMethod && maybeBasicAuthMethod.basic != null;
|
168
|
+
}
|
169
|
+
|
170
|
+
// src/http/guards/isHmacMethod.ts
|
171
|
+
function isHmacMethod(maybeHmacMethod) {
|
172
|
+
return typeof maybeHmacMethod === "object" && maybeHmacMethod !== null && "secretKey" in maybeHmacMethod && maybeHmacMethod.secretKey != null;
|
173
|
+
}
|
174
|
+
|
175
|
+
// src/http/guards/isJwtAuthMethod.ts
|
176
|
+
function isJwtAuthMethod(maybeJwtAuthMethod) {
|
177
|
+
return typeof maybeJwtAuthMethod === "object" && maybeJwtAuthMethod !== null && "jwt" in maybeJwtAuthMethod && maybeJwtAuthMethod.jwt != null;
|
178
|
+
}
|
179
|
+
|
180
|
+
// src/http/discriminateAuthMethod.ts
|
163
181
|
async function discriminateAuthMethod(auth) {
|
164
|
-
|
165
|
-
|
182
|
+
let authMethod;
|
183
|
+
if (isBasicAuthMethod(auth)) {
|
184
|
+
authMethod = {
|
166
185
|
type: "basic",
|
167
186
|
auth: {
|
168
187
|
decodeResource: auth.decodeResource,
|
169
188
|
login: auth.basic.login
|
170
189
|
}
|
171
190
|
};
|
172
|
-
} else if (
|
191
|
+
} else if (isJwtAuthMethod(auth)) {
|
173
192
|
const jwt = auth.jwt;
|
174
193
|
let verificationFunction;
|
175
|
-
if ("
|
194
|
+
if ("signatureKey" in jwt) {
|
176
195
|
verificationFunction = async (token) => {
|
177
|
-
const { payload } = await (0, import_jose.jwtVerify)(
|
196
|
+
const { payload } = await (0, import_jose.jwtVerify)(
|
197
|
+
token,
|
198
|
+
Buffer.from(jwt.signatureKey)
|
199
|
+
);
|
178
200
|
return payload;
|
179
201
|
};
|
180
202
|
} else {
|
@@ -182,7 +204,7 @@ async function discriminateAuthMethod(auth) {
|
|
182
204
|
if ("jwksPublicKeyUrl" in jwt) {
|
183
205
|
const jwksResponse = await fetch(jwt.jwksPublicKeyUrl);
|
184
206
|
jwks = (await jwksResponse.json()).keys;
|
185
|
-
} else {
|
207
|
+
} else if ("jwksPublicKey" in jwt) {
|
186
208
|
jwks = [jwt.jwksPublicKey];
|
187
209
|
}
|
188
210
|
verificationFunction = async (token) => {
|
@@ -196,35 +218,35 @@ async function discriminateAuthMethod(auth) {
|
|
196
218
|
}
|
197
219
|
};
|
198
220
|
}
|
199
|
-
|
221
|
+
authMethod = {
|
200
222
|
type: "jwt",
|
201
223
|
auth: {
|
202
224
|
decodeResource: auth.decodeResource,
|
203
225
|
verificationFunction
|
204
226
|
}
|
205
227
|
};
|
206
|
-
} else if (
|
207
|
-
|
208
|
-
type: "
|
209
|
-
auth: {
|
210
|
-
secretKey: auth.secretKey
|
211
|
-
}
|
212
|
-
};
|
213
|
-
} else {
|
214
|
-
return {
|
215
|
-
type: "jwt",
|
228
|
+
} else if (isHmacMethod(auth)) {
|
229
|
+
authMethod = {
|
230
|
+
type: "hmac",
|
216
231
|
auth: {
|
217
|
-
|
218
|
-
verificationFunction: async (
|
219
|
-
const
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
232
|
+
secretKeys: auth.hmac.secretKeys,
|
233
|
+
verificationFunction: async (method, path, body, timestamp, nonce, signature, secretKey) => {
|
234
|
+
const hmac = (0, import_crypto.createHmac)("sha256", secretKey);
|
235
|
+
hmac.update(`${method}
|
236
|
+
${path}
|
237
|
+
${body}
|
238
|
+
${timestamp}
|
239
|
+
${nonce}`);
|
240
|
+
const digest = hmac.digest("base64");
|
241
|
+
return digest === signature;
|
224
242
|
}
|
225
243
|
}
|
226
244
|
};
|
227
245
|
}
|
246
|
+
if (authMethod == null) {
|
247
|
+
throw new Error("Invalid auth method");
|
248
|
+
}
|
249
|
+
return authMethod;
|
228
250
|
}
|
229
251
|
|
230
252
|
// src/http/guards/hasPermissionChecks.ts
|
@@ -242,19 +264,14 @@ function hasScopeChecks(maybePermissionedAuth) {
|
|
242
264
|
return typeof maybePermissionedAuth === "object" && maybePermissionedAuth !== null && "requiredScope" in maybePermissionedAuth && maybePermissionedAuth.requiredScope != null;
|
243
265
|
}
|
244
266
|
|
245
|
-
// src/http/guards/isSystemAuthMethod.ts
|
246
|
-
function isSystemAuthMethod(maybeSystemAuthMethod) {
|
247
|
-
return typeof maybeSystemAuthMethod === "object" && maybeSystemAuthMethod !== null && "secretKey" in maybeSystemAuthMethod;
|
248
|
-
}
|
249
|
-
|
250
267
|
// src/http/middleware/request/auth.middleware.ts
|
251
268
|
var invalidAuthorizationTokenFormat = [
|
252
269
|
401,
|
253
270
|
"Invalid Authorization token format."
|
254
271
|
];
|
255
|
-
var
|
272
|
+
var invalidAuthorizationSignature = [
|
256
273
|
403,
|
257
|
-
"Invalid Authorization
|
274
|
+
"Invalid Authorization signature."
|
258
275
|
];
|
259
276
|
var invalidAuthorizationTokenPermissions = [
|
260
277
|
403,
|
@@ -281,6 +298,16 @@ var authorizationTokenRequired = [
|
|
281
298
|
401,
|
282
299
|
"Authorization token required."
|
283
300
|
];
|
301
|
+
var invalidInstantiation = [
|
302
|
+
500,
|
303
|
+
"Invalid instantiation of authorization method."
|
304
|
+
];
|
305
|
+
function parseHmacTokenPart(part, expectedKey) {
|
306
|
+
if (!part) return void 0;
|
307
|
+
const [key, ...rest] = part.split("=");
|
308
|
+
if (key !== expectedKey || rest.length === 0) return void 0;
|
309
|
+
return rest.join("=");
|
310
|
+
}
|
284
311
|
async function checkAuthorizationToken(authorizationMethod, globalOptions, authorizationToken, req) {
|
285
312
|
if (authorizationMethod == null) {
|
286
313
|
return void 0;
|
@@ -292,27 +319,54 @@ async function checkAuthorizationToken(authorizationMethod, globalOptions, autho
|
|
292
319
|
if (authorizationToken == null) {
|
293
320
|
return authorizationTokenRequired;
|
294
321
|
}
|
295
|
-
const [tokenPrefix,
|
322
|
+
const [tokenPrefix, ...tokenParts] = authorizationToken.split(" ");
|
323
|
+
if (!tokenParts.length || !tokenPrefix) {
|
324
|
+
return invalidAuthorizationTokenFormat;
|
325
|
+
}
|
296
326
|
let resourceId;
|
297
327
|
const { type, auth } = await discriminateAuthMethod(
|
298
328
|
collapsedAuthorizationMethod
|
299
329
|
);
|
300
330
|
switch (type) {
|
301
|
-
case "
|
302
|
-
|
331
|
+
case "hmac": {
|
332
|
+
const [keyId, timestamp, nonce, signature] = tokenParts;
|
333
|
+
if (keyId == null || timestamp == null || nonce == null || signature == null || tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? "HMAC")) {
|
303
334
|
return invalidAuthorizationToken;
|
304
335
|
}
|
336
|
+
if (!collapsedAuthorizationMethod.hmac?.secretKeys) {
|
337
|
+
return invalidInstantiation;
|
338
|
+
}
|
339
|
+
const parsedKeyId = parseHmacTokenPart(keyId, "keyId");
|
340
|
+
const parsedTimestamp = parseHmacTokenPart(timestamp, "ts");
|
341
|
+
const parsedNonce = parseHmacTokenPart(nonce, "nonce");
|
342
|
+
const parsedSignature = parseHmacTokenPart(signature, "signature");
|
343
|
+
if (!parsedKeyId || !parsedTimestamp || !parsedNonce || !parsedSignature) {
|
344
|
+
return invalidAuthorizationTokenFormat;
|
345
|
+
}
|
346
|
+
const verificationResult = await auth.verificationFunction(
|
347
|
+
req?.method ?? "",
|
348
|
+
req?.path ?? "",
|
349
|
+
JSON.stringify(req?.body ?? ""),
|
350
|
+
parsedTimestamp,
|
351
|
+
parsedNonce,
|
352
|
+
parsedSignature,
|
353
|
+
collapsedAuthorizationMethod.hmac.secretKeys[parsedKeyId]
|
354
|
+
);
|
355
|
+
if (!verificationResult) {
|
356
|
+
return invalidAuthorizationSignature;
|
357
|
+
}
|
305
358
|
resourceId = null;
|
306
359
|
break;
|
307
360
|
}
|
308
361
|
case "jwt": {
|
362
|
+
const [token] = tokenParts;
|
309
363
|
if (tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? "Bearer")) {
|
310
364
|
return invalidAuthorizationTokenFormat;
|
311
365
|
}
|
312
366
|
try {
|
313
367
|
const decodedJwt = "decodeResource" in auth && auth.decodeResource ? await auth.decodeResource(token) : "verificationFunction" in auth && auth.verificationFunction ? await auth.verificationFunction(token) : void 0;
|
314
368
|
if (!decodedJwt) {
|
315
|
-
return
|
369
|
+
return invalidAuthorizationToken;
|
316
370
|
}
|
317
371
|
resourceId = decodedJwt;
|
318
372
|
} catch (error) {
|
@@ -322,6 +376,7 @@ async function checkAuthorizationToken(authorizationMethod, globalOptions, autho
|
|
322
376
|
break;
|
323
377
|
}
|
324
378
|
case "basic": {
|
379
|
+
const [token] = tokenParts;
|
325
380
|
if (tokenPrefix !== (collapsedAuthorizationMethod.tokenPrefix ?? "Basic")) {
|
326
381
|
return invalidAuthorizationTokenFormat;
|
327
382
|
}
|
@@ -345,9 +400,12 @@ async function checkAuthorizationToken(authorizationMethod, globalOptions, autho
|
|
345
400
|
(0, import_common2.isNever)(type);
|
346
401
|
return [401, "Invalid Authorization method."];
|
347
402
|
}
|
348
|
-
if (
|
403
|
+
if (isHmacMethod(collapsedAuthorizationMethod) && resourceId == null) {
|
349
404
|
return;
|
350
405
|
}
|
406
|
+
if (resourceId == null) {
|
407
|
+
return invalidAuthorizationToken;
|
408
|
+
}
|
351
409
|
if (hasScopeChecks(collapsedAuthorizationMethod)) {
|
352
410
|
if (collapsedAuthorizationMethod.surfaceScopes) {
|
353
411
|
const resourceScopes = await collapsedAuthorizationMethod.surfaceScopes(
|
@@ -1345,13 +1403,15 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
1345
1403
|
const maybeTypedHandler = middlewareOrMiddlewareAndTypedHandler[middlewareOrMiddlewareAndTypedHandler.length - 1];
|
1346
1404
|
if (isTypedHandler(maybeTypedHandler)) {
|
1347
1405
|
const { contractDetails, handlers } = maybeTypedHandler;
|
1348
|
-
const
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
);
|
1406
|
+
const finalHandlers = [];
|
1407
|
+
if (isExpressLikeSchemaHandler(contractDetailsOrMiddlewareOrTypedHandler)) {
|
1408
|
+
finalHandlers.push(
|
1409
|
+
contractDetailsOrMiddlewareOrTypedHandler
|
1410
|
+
);
|
1411
|
+
}
|
1412
|
+
finalHandlers.push(...middlewareOrMiddlewareAndTypedHandler);
|
1413
|
+
finalHandlers.push(...handlers);
|
1414
|
+
const router = this.registerRoute(method, path, registrationMethod, contractDetails, ...finalHandlers);
|
1355
1415
|
return router;
|
1356
1416
|
} else {
|
1357
1417
|
if (isExpressLikeSchemaHandler(contractDetailsOrMiddlewareOrTypedHandler) || isTypedHandler(contractDetailsOrMiddlewareOrTypedHandler)) {
|
@@ -1560,6 +1620,10 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
1560
1620
|
].forEach((arg) => {
|
1561
1621
|
if (isForklaunchRouter(arg)) {
|
1562
1622
|
this.routers.push(arg);
|
1623
|
+
arg.routerOptions = {
|
1624
|
+
...this.routerOptions ?? {},
|
1625
|
+
...arg.routerOptions ?? {}
|
1626
|
+
};
|
1563
1627
|
}
|
1564
1628
|
});
|
1565
1629
|
return this.registerNestableMiddlewareHandler(
|