@forklaunch/core 1.5.19 → 1.6.0
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/discriminateAuthMethod.d.ts.map +1 -1
- package/lib/http/index.js +66 -10
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +64 -8
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/middleware/request/auth.middleware.d.ts.map +1 -1
- package/lib/http/middleware/request/authLogContext.d.ts +44 -0
- package/lib/http/middleware/request/authLogContext.d.ts.map +1 -0
- package/lib/persistence/fieldEncryptor.d.ts +137 -9
- package/lib/persistence/fieldEncryptor.d.ts.map +1 -1
- package/lib/persistence/index.d.ts +2 -1
- package/lib/persistence/index.d.ts.map +1 -1
- package/lib/persistence/index.js +409 -26
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +391 -26
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/persistence/keyRotation.d.ts +118 -0
- package/lib/persistence/keyRotation.d.ts.map +1 -0
- package/package.json +22 -22
package/lib/http/index.mjs
CHANGED
|
@@ -733,17 +733,20 @@ async function discriminateAuthMethod(auth, openTelemetryCollector) {
|
|
|
733
733
|
jwks = [jwt.jwksPublicKey];
|
|
734
734
|
}
|
|
735
735
|
verificationFunction = async (token) => {
|
|
736
|
+
let lastError;
|
|
736
737
|
for (const key of jwks) {
|
|
737
738
|
try {
|
|
738
739
|
const { payload } = await jwtVerify(token, key);
|
|
739
740
|
return payload;
|
|
740
|
-
} catch {
|
|
741
|
+
} catch (error) {
|
|
742
|
+
lastError = error;
|
|
741
743
|
cachedJwks.value = null;
|
|
742
744
|
cachedJwks.lastUpdated = null;
|
|
743
745
|
cachedJwks.ttl = DEFAULT_TTL;
|
|
744
746
|
continue;
|
|
745
747
|
}
|
|
746
748
|
}
|
|
749
|
+
if (lastError !== void 0) throw lastError;
|
|
747
750
|
};
|
|
748
751
|
}
|
|
749
752
|
authMethod = {
|
|
@@ -812,6 +815,58 @@ function hasSubscriptionChecks(maybeSubscriptionAuth) {
|
|
|
812
815
|
return typeof maybeSubscriptionAuth === "object" && maybeSubscriptionAuth !== null && "requireActiveSubscription" in maybeSubscriptionAuth && maybeSubscriptionAuth.requireActiveSubscription === true;
|
|
813
816
|
}
|
|
814
817
|
|
|
818
|
+
// src/http/middleware/request/authLogContext.ts
|
|
819
|
+
import { createHash } from "crypto";
|
|
820
|
+
import { decodeJwt, decodeProtectedHeader, errors as joseErrors } from "jose";
|
|
821
|
+
var FINGERPRINT_LENGTH = 8;
|
|
822
|
+
var MAX_CLAIM_LENGTH = 128;
|
|
823
|
+
function bounded(value) {
|
|
824
|
+
return typeof value === "string" && value.length > 0 ? value.slice(0, MAX_CLAIM_LENGTH) : void 0;
|
|
825
|
+
}
|
|
826
|
+
function authLogContext(headerValue) {
|
|
827
|
+
if (typeof headerValue !== "string" || headerValue.length === 0) {
|
|
828
|
+
return { hasToken: false };
|
|
829
|
+
}
|
|
830
|
+
const context2 = {
|
|
831
|
+
hasToken: true,
|
|
832
|
+
tokenFingerprint: createHash("sha256").update(headerValue).digest("hex").slice(0, FINGERPRINT_LENGTH)
|
|
833
|
+
};
|
|
834
|
+
const parts = headerValue.trim().split(/\s+/);
|
|
835
|
+
const candidate = parts[parts.length - 1];
|
|
836
|
+
if (candidate.split(".").length !== 3) {
|
|
837
|
+
return context2;
|
|
838
|
+
}
|
|
839
|
+
try {
|
|
840
|
+
const payload = decodeJwt(candidate);
|
|
841
|
+
const header = decodeProtectedHeader(candidate);
|
|
842
|
+
context2.claimed = {
|
|
843
|
+
sub: bounded(payload.sub),
|
|
844
|
+
organizationId: bounded(payload.organizationId),
|
|
845
|
+
iss: bounded(payload.iss),
|
|
846
|
+
exp: typeof payload.exp === "number" ? payload.exp : void 0,
|
|
847
|
+
kid: bounded(header.kid)
|
|
848
|
+
};
|
|
849
|
+
} catch {
|
|
850
|
+
}
|
|
851
|
+
return context2;
|
|
852
|
+
}
|
|
853
|
+
function jwtFailureReason(error) {
|
|
854
|
+
if (error instanceof joseErrors.JWTExpired) return "jwt_expired";
|
|
855
|
+
if (error instanceof joseErrors.JWTClaimValidationFailed) {
|
|
856
|
+
return `jwt_claim_${error.claim}`;
|
|
857
|
+
}
|
|
858
|
+
if (error instanceof joseErrors.JWSSignatureVerificationFailed) {
|
|
859
|
+
return "jwt_bad_signature";
|
|
860
|
+
}
|
|
861
|
+
if (error instanceof joseErrors.JWKSNoMatchingKey) return "jwks_no_key";
|
|
862
|
+
if (error instanceof joseErrors.JWKSTimeout) return "jwks_unavailable";
|
|
863
|
+
if (error instanceof joseErrors.JWTInvalid || error instanceof joseErrors.JWSInvalid) {
|
|
864
|
+
return "jwt_malformed";
|
|
865
|
+
}
|
|
866
|
+
if (error instanceof joseErrors.JOSEError) return error.code.toLowerCase();
|
|
867
|
+
return "unknown";
|
|
868
|
+
}
|
|
869
|
+
|
|
815
870
|
// src/http/middleware/request/auth.middleware.ts
|
|
816
871
|
var invalidAuthorizationTokenFormat = [
|
|
817
872
|
401,
|
|
@@ -927,13 +982,14 @@ async function checkAuthorizationToken(req, authorizationMethod, authorizationTo
|
|
|
927
982
|
}
|
|
928
983
|
sessionPayload = decodedJwt;
|
|
929
984
|
} catch (error) {
|
|
930
|
-
req?.openTelemetryCollector?.
|
|
985
|
+
req?.openTelemetryCollector?.warn(
|
|
931
986
|
"JWT Verification Failed",
|
|
932
987
|
meta({
|
|
933
|
-
error,
|
|
988
|
+
reason: jwtFailureReason(error),
|
|
989
|
+
error: error instanceof Error ? error.message : String(error),
|
|
934
990
|
method: req.method,
|
|
935
991
|
path: req.path,
|
|
936
|
-
token
|
|
992
|
+
...authLogContext(token)
|
|
937
993
|
})
|
|
938
994
|
);
|
|
939
995
|
return invalidAuthorizationToken;
|
|
@@ -1084,13 +1140,13 @@ async function parseRequestAuth(req, res, next) {
|
|
|
1084
1140
|
const token = req.headers[auth?.headerName ?? "Authorization"] || req.headers[auth?.headerName ?? "authorization"];
|
|
1085
1141
|
const [error, message] = await checkAuthorizationToken(req, auth, token, req._globalOptions?.()?.auth, access) ?? [];
|
|
1086
1142
|
if (error != null) {
|
|
1087
|
-
req.openTelemetryCollector?.
|
|
1143
|
+
req.openTelemetryCollector?.warn(
|
|
1088
1144
|
message || "Authorization Failed",
|
|
1089
1145
|
meta({
|
|
1090
1146
|
statusCode: error,
|
|
1091
1147
|
method: req.method,
|
|
1092
1148
|
path: req.path,
|
|
1093
|
-
token
|
|
1149
|
+
...authLogContext(token)
|
|
1094
1150
|
})
|
|
1095
1151
|
);
|
|
1096
1152
|
res.type("text/plain");
|
|
@@ -4319,7 +4375,7 @@ function generateOpenApiSpecs(schemaValidator, serverUrls, serverDescriptions, a
|
|
|
4319
4375
|
}
|
|
4320
4376
|
|
|
4321
4377
|
// src/http/telemetry/auditLogger.ts
|
|
4322
|
-
import { createHash } from "crypto";
|
|
4378
|
+
import { createHash as createHash2 } from "crypto";
|
|
4323
4379
|
var AuditLogger = class {
|
|
4324
4380
|
_otel;
|
|
4325
4381
|
constructor(otel) {
|
|
@@ -4352,7 +4408,7 @@ var AuditLogger = class {
|
|
|
4352
4408
|
if (body === void 0 || body === null || body === "") {
|
|
4353
4409
|
return "";
|
|
4354
4410
|
}
|
|
4355
|
-
return
|
|
4411
|
+
return createHash2("sha256").update(body).digest("hex");
|
|
4356
4412
|
}
|
|
4357
4413
|
};
|
|
4358
4414
|
|