@heavybit/pendoadmin-shared-lib 1.6.0 → 1.7.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.
Files changed (54) hide show
  1. package/dist/common/gateway-signature.d.ts +49 -0
  2. package/dist/common/gateway-signature.d.ts.map +1 -0
  3. package/dist/common/gateway-signature.js +99 -0
  4. package/dist/common/gateway-signature.js.map +1 -0
  5. package/dist/common/index.d.ts +1 -0
  6. package/dist/common/index.d.ts.map +1 -1
  7. package/dist/common/index.js +1 -0
  8. package/dist/common/index.js.map +1 -1
  9. package/dist/express/auth.middleware.d.ts +5 -4
  10. package/dist/express/auth.middleware.d.ts.map +1 -1
  11. package/dist/express/auth.middleware.js +49 -65
  12. package/dist/express/auth.middleware.js.map +1 -1
  13. package/dist/logging/index.d.ts +1 -0
  14. package/dist/logging/index.d.ts.map +1 -1
  15. package/dist/logging/index.js +5 -2
  16. package/dist/logging/index.js.map +1 -1
  17. package/dist/logging/redact.d.ts +16 -0
  18. package/dist/logging/redact.d.ts.map +1 -0
  19. package/dist/logging/redact.js +83 -0
  20. package/dist/logging/redact.js.map +1 -0
  21. package/dist/nestjs/auth.guard.d.ts +2 -0
  22. package/dist/nestjs/auth.guard.d.ts.map +1 -1
  23. package/dist/nestjs/auth.guard.js +11 -3
  24. package/dist/nestjs/auth.guard.js.map +1 -1
  25. package/dist/nestjs/permission.guard.js +5 -4
  26. package/dist/nestjs/permission.guard.js.map +1 -1
  27. package/dist/rate-limit/create-rate-limiter.d.ts +7 -1
  28. package/dist/rate-limit/create-rate-limiter.d.ts.map +1 -1
  29. package/dist/rate-limit/create-rate-limiter.js +12 -2
  30. package/dist/rate-limit/create-rate-limiter.js.map +1 -1
  31. package/dist/rate-limit/index.d.ts +1 -1
  32. package/dist/rate-limit/index.d.ts.map +1 -1
  33. package/dist/rate-limit/index.js +1 -1
  34. package/dist/rate-limit/index.js.map +1 -1
  35. package/dist/types/index.d.ts +2 -0
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/dist/types/index.js +2 -0
  38. package/dist/types/index.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/common/gateway-signature.ts +124 -0
  41. package/src/common/index.ts +1 -0
  42. package/src/express/auth.middleware.ts +46 -64
  43. package/src/logging/index.ts +6 -2
  44. package/src/logging/redact.ts +84 -0
  45. package/src/nestjs/auth.guard.ts +12 -3
  46. package/src/nestjs/permission.guard.ts +5 -5
  47. package/src/rate-limit/create-rate-limiter.ts +13 -3
  48. package/src/rate-limit/index.ts +1 -1
  49. package/src/types/index.ts +2 -0
  50. package/tests/auth-middleware.test.mjs +91 -0
  51. package/tests/gateway-signature.test.mjs +93 -0
  52. package/tests/nestjs-guards.test.mjs +45 -0
  53. package/tests/rate-limit-key.test.mjs +25 -0
  54. package/tests/redact.test.mjs +61 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Signed gateway identity.
3
+ *
4
+ * The api-gateway (and any internal service forwarding a caller's identity)
5
+ * signs the identity headers it injects with GATEWAY_SIGNING_SECRET. Downstream
6
+ * services verify the signature before trusting x-user-id / x-is-superadmin /
7
+ * x-user-permissions, so a request that reaches a service port directly, or
8
+ * slips past the gateway with its own headers, cannot impersonate anyone.
9
+ *
10
+ * The api-gateway keeps its own copy of the signer
11
+ * (api-gateway/src/utils/gateway-signature.ts). Any change to the canonical
12
+ * string below must be made in both places — the shared test vector in both
13
+ * test suites pins the format.
14
+ */
15
+ export declare const GATEWAY_SIGNATURE_HEADER = "x-gateway-signature";
16
+ export declare const GATEWAY_TIMESTAMP_HEADER = "x-gateway-ts";
17
+ /** Identity headers covered by the signature, in canonical order. */
18
+ export declare const GATEWAY_IDENTITY_HEADERS: readonly ["x-user-id", "x-user-email", "x-company-id", "x-company-slug", "x-user-roles", "x-user-permissions", "x-is-superadmin", "x-otp-verified"];
19
+ /** Default allowed clock skew between signer and verifier. */
20
+ export declare const GATEWAY_SIGNATURE_MAX_SKEW_SECONDS = 60;
21
+ type HeaderBag = Record<string, string | string[] | undefined>;
22
+ /**
23
+ * Signature headers for the identity headers already present in `headers`
24
+ * (lower-case names). Merge the result into the outgoing request headers.
25
+ */
26
+ export declare function signGatewayIdentity(headers: HeaderBag, secret: string, nowMs?: number): Record<typeof GATEWAY_SIGNATURE_HEADER | typeof GATEWAY_TIMESTAMP_HEADER, string>;
27
+ export interface VerifyGatewayIdentityOptions {
28
+ maxSkewSeconds?: number;
29
+ nowMs?: number;
30
+ }
31
+ /** True when the identity headers carry a valid, fresh signature from `secret`. */
32
+ export declare function verifyGatewayIdentity(headers: HeaderBag, secret: string, options?: VerifyGatewayIdentityOptions): boolean;
33
+ /**
34
+ * The secret services sign and verify gateway identity with. Unset means
35
+ * unsigned identity is accepted only outside production (see
36
+ * isUnsignedGatewayIdentityAllowed).
37
+ */
38
+ export declare function gatewaySigningSecret(): string;
39
+ /** Local development may run services without a signing secret; production never trusts unsigned identity. */
40
+ export declare function isUnsignedGatewayIdentityAllowed(): boolean;
41
+ /**
42
+ * Whether a request's gateway identity headers can be trusted: a valid
43
+ * signature when a secret is configured, otherwise only outside production.
44
+ */
45
+ export declare function isTrustedGatewayIdentity(headers: HeaderBag): boolean;
46
+ /** Direct JWT validation is a development convenience only; production requests must come through the gateway. */
47
+ export declare function isDirectJwtFallbackAllowed(): boolean;
48
+ export {};
49
+ //# sourceMappingURL=gateway-signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-signature.d.ts","sourceRoot":"","sources":["../../src/common/gateway-signature.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAGvD,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,qJAS3B,CAAC;AAEX,8DAA8D;AAC9D,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAErD,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;AAoB/D;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAmB,GACzB,MAAM,CAAC,OAAO,wBAAwB,GAAG,OAAO,wBAAwB,EAAE,MAAM,CAAC,CAMnF;AAED,MAAM,WAAW,4BAA4B;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAYT;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,8GAA8G;AAC9G,wBAAgB,gCAAgC,IAAI,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAIpE;AAED,kHAAkH;AAClH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD"}
@@ -0,0 +1,99 @@
1
+ import crypto from 'node:crypto';
2
+ /**
3
+ * Signed gateway identity.
4
+ *
5
+ * The api-gateway (and any internal service forwarding a caller's identity)
6
+ * signs the identity headers it injects with GATEWAY_SIGNING_SECRET. Downstream
7
+ * services verify the signature before trusting x-user-id / x-is-superadmin /
8
+ * x-user-permissions, so a request that reaches a service port directly, or
9
+ * slips past the gateway with its own headers, cannot impersonate anyone.
10
+ *
11
+ * The api-gateway keeps its own copy of the signer
12
+ * (api-gateway/src/utils/gateway-signature.ts). Any change to the canonical
13
+ * string below must be made in both places — the shared test vector in both
14
+ * test suites pins the format.
15
+ */
16
+ export const GATEWAY_SIGNATURE_HEADER = 'x-gateway-signature';
17
+ export const GATEWAY_TIMESTAMP_HEADER = 'x-gateway-ts';
18
+ const SIGNATURE_VERSION = 'v1';
19
+ /** Identity headers covered by the signature, in canonical order. */
20
+ export const GATEWAY_IDENTITY_HEADERS = [
21
+ 'x-user-id',
22
+ 'x-user-email',
23
+ 'x-company-id',
24
+ 'x-company-slug',
25
+ 'x-user-roles',
26
+ 'x-user-permissions',
27
+ 'x-is-superadmin',
28
+ 'x-otp-verified',
29
+ ];
30
+ /** Default allowed clock skew between signer and verifier. */
31
+ export const GATEWAY_SIGNATURE_MAX_SKEW_SECONDS = 60;
32
+ function headerValue(headers, name) {
33
+ const value = headers[name];
34
+ return (Array.isArray(value) ? value[0] : value) ?? '';
35
+ }
36
+ function canonicalString(headers, timestamp) {
37
+ return [
38
+ SIGNATURE_VERSION,
39
+ timestamp,
40
+ headerValue(headers, 'x-correlation-id'),
41
+ ...GATEWAY_IDENTITY_HEADERS.map((name) => headerValue(headers, name)),
42
+ ].join('\n');
43
+ }
44
+ function hmac(secret, payload) {
45
+ return crypto.createHmac('sha256', secret).update(payload).digest('hex');
46
+ }
47
+ /**
48
+ * Signature headers for the identity headers already present in `headers`
49
+ * (lower-case names). Merge the result into the outgoing request headers.
50
+ */
51
+ export function signGatewayIdentity(headers, secret, nowMs = Date.now()) {
52
+ const timestamp = String(Math.floor(nowMs / 1000));
53
+ return {
54
+ [GATEWAY_SIGNATURE_HEADER]: hmac(secret, canonicalString(headers, timestamp)),
55
+ [GATEWAY_TIMESTAMP_HEADER]: timestamp,
56
+ };
57
+ }
58
+ /** True when the identity headers carry a valid, fresh signature from `secret`. */
59
+ export function verifyGatewayIdentity(headers, secret, options = {}) {
60
+ if (!secret)
61
+ return false;
62
+ const { maxSkewSeconds = GATEWAY_SIGNATURE_MAX_SKEW_SECONDS, nowMs = Date.now() } = options;
63
+ const timestamp = headerValue(headers, GATEWAY_TIMESTAMP_HEADER);
64
+ const signature = headerValue(headers, GATEWAY_SIGNATURE_HEADER);
65
+ if (!/^\d+$/.test(timestamp) || !/^[0-9a-f]{64}$/.test(signature))
66
+ return false;
67
+ if (Math.abs(nowMs / 1000 - Number(timestamp)) > maxSkewSeconds)
68
+ return false;
69
+ const expected = Buffer.from(hmac(secret, canonicalString(headers, timestamp)), 'hex');
70
+ const provided = Buffer.from(signature, 'hex');
71
+ return expected.length === provided.length && crypto.timingSafeEqual(expected, provided);
72
+ }
73
+ /**
74
+ * The secret services sign and verify gateway identity with. Unset means
75
+ * unsigned identity is accepted only outside production (see
76
+ * isUnsignedGatewayIdentityAllowed).
77
+ */
78
+ export function gatewaySigningSecret() {
79
+ return process.env.GATEWAY_SIGNING_SECRET || '';
80
+ }
81
+ /** Local development may run services without a signing secret; production never trusts unsigned identity. */
82
+ export function isUnsignedGatewayIdentityAllowed() {
83
+ return !gatewaySigningSecret() && process.env.NODE_ENV !== 'production';
84
+ }
85
+ /**
86
+ * Whether a request's gateway identity headers can be trusted: a valid
87
+ * signature when a secret is configured, otherwise only outside production.
88
+ */
89
+ export function isTrustedGatewayIdentity(headers) {
90
+ const secret = gatewaySigningSecret();
91
+ if (secret)
92
+ return verifyGatewayIdentity(headers, secret);
93
+ return isUnsignedGatewayIdentityAllowed();
94
+ }
95
+ /** Direct JWT validation is a development convenience only; production requests must come through the gateway. */
96
+ export function isDirectJwtFallbackAllowed() {
97
+ return process.env.NODE_ENV !== 'production';
98
+ }
99
+ //# sourceMappingURL=gateway-signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-signature.js","sourceRoot":"","sources":["../../src/common/gateway-signature.ts"],"names":[],"mappings":"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"}
@@ -5,4 +5,5 @@ export * from './uuid.utils.js';
5
5
  export * from './response.utils.js';
6
6
  export * from './timezone.utils.js';
7
7
  export * from './permission.utils.js';
8
+ export * from './gateway-signature.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
@@ -5,4 +5,5 @@ export * from './uuid.utils.js';
5
5
  export * from './response.utils.js';
6
6
  export * from './timezone.utils.js';
7
7
  export * from './permission.utils.js';
8
+ export * from './gateway-signature.js';
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
@@ -9,12 +9,13 @@ declare global {
9
9
  }
10
10
  /**
11
11
  * Auth middleware for downstream services (behind API gateway).
12
- * Reads user context from gateway-injected headers.
13
- * Falls back to JWT validation if headers are missing (direct access).
12
+ * Reads user context from gateway-injected headers, trusted only with a valid
13
+ * gateway signature (GATEWAY_SIGNING_SECRET). Outside production it falls back
14
+ * to direct JWT validation for local development.
14
15
  */
15
- export declare function authenticateFromGateway(jwtSecret?: string): (req: Request, _res: Response, next: NextFunction) => void;
16
+ export declare function authenticateFromGateway(jwtSecret?: string): (req: Request, res: Response, next: NextFunction) => void;
16
17
  /**
17
- * Optional auth — attaches user if present, continues if not.
18
+ * Optional auth — attaches user if present (and trusted), continues if not.
18
19
  */
19
20
  export declare function optionalAuthFromGateway(jwtSecret?: string): (req: Request, _res: Response, next: NextFunction) => void;
20
21
  //# sourceMappingURL=auth.middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.middleware.d.ts","sourceRoot":"","sources":["../../src/express/auth.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAapE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,SAAS,CAAC;SAClB;KACF;CACF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE,MAAM,IAChD,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAsChE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE,MAAM,IAChD,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA6BhE"}
1
+ {"version":3,"file":"auth.middleware.d.ts","sourceRoot":"","sources":["../../src/express/auth.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAapE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,SAAS,CAAC;SAClB;KACF;CACF;AAoCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE,MAAM,IAChD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAQ/D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE,MAAM,IAChD,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAKhE"}
@@ -1,4 +1,5 @@
1
1
  import { verifyToken, extractBearerToken } from '../common/jwt.utils.js';
2
+ import { isTrustedGatewayIdentity, isDirectJwtFallbackAllowed } from '../common/gateway-signature.js';
2
3
  import { GATEWAY_HEADERS } from '../types/index.js';
3
4
  /** Parse a header value that may be a JSON array string or comma-separated. */
4
5
  function parseArrayHeader(value) {
@@ -13,83 +14,66 @@ function parseArrayHeader(value) {
13
14
  }
14
15
  return trimmed.split(',').filter(Boolean);
15
16
  }
17
+ /** The caller from signed gateway headers, or null when absent or unsigned/forged. */
18
+ function userFromGatewayHeaders(req) {
19
+ const userId = req.headers[GATEWAY_HEADERS.USER_ID];
20
+ if (!userId || !isTrustedGatewayIdentity(req.headers))
21
+ return null;
22
+ return {
23
+ id: userId,
24
+ email: req.headers[GATEWAY_HEADERS.USER_EMAIL] || '',
25
+ companyId: req.headers[GATEWAY_HEADERS.COMPANY_ID] || '',
26
+ roles: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_ROLES]),
27
+ permissions: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_PERMISSIONS]),
28
+ isSuperAdmin: req.headers[GATEWAY_HEADERS.IS_SUPERADMIN] === 'true',
29
+ };
30
+ }
31
+ /** The caller from a bearer JWT — development only (direct service access). */
32
+ function userFromBearerToken(req, jwtSecret) {
33
+ if (!jwtSecret || !isDirectJwtFallbackAllowed())
34
+ return null;
35
+ const token = extractBearerToken(req.headers.authorization);
36
+ if (!token)
37
+ return null;
38
+ try {
39
+ const payload = verifyToken(token, jwtSecret);
40
+ return {
41
+ id: payload.sub,
42
+ email: payload.email,
43
+ companyId: payload.companyId,
44
+ roles: payload.roles || [],
45
+ permissions: payload.permissions || [],
46
+ isSuperAdmin: payload.isSuperAdmin || false,
47
+ };
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
16
53
  /**
17
54
  * Auth middleware for downstream services (behind API gateway).
18
- * Reads user context from gateway-injected headers.
19
- * Falls back to JWT validation if headers are missing (direct access).
55
+ * Reads user context from gateway-injected headers, trusted only with a valid
56
+ * gateway signature (GATEWAY_SIGNING_SECRET). Outside production it falls back
57
+ * to direct JWT validation for local development.
20
58
  */
21
59
  export function authenticateFromGateway(jwtSecret) {
22
- return (req, _res, next) => {
23
- // Method 1: Read gateway-injected headers
24
- const userId = req.headers[GATEWAY_HEADERS.USER_ID];
25
- if (userId) {
26
- req.user = {
27
- id: userId,
28
- email: req.headers[GATEWAY_HEADERS.USER_EMAIL] || '',
29
- companyId: req.headers[GATEWAY_HEADERS.COMPANY_ID] || '',
30
- roles: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_ROLES]),
31
- permissions: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_PERMISSIONS]),
32
- isSuperAdmin: req.headers[GATEWAY_HEADERS.IS_SUPERADMIN] === 'true',
33
- };
60
+ return (req, res, next) => {
61
+ const user = userFromGatewayHeaders(req) ?? userFromBearerToken(req, jwtSecret);
62
+ if (user) {
63
+ req.user = user;
34
64
  return next();
35
65
  }
36
- // Method 2: Direct JWT validation (for development / direct access)
37
- if (jwtSecret) {
38
- const token = extractBearerToken(req.headers.authorization);
39
- if (token) {
40
- try {
41
- const payload = verifyToken(token, jwtSecret);
42
- req.user = {
43
- id: payload.sub,
44
- email: payload.email,
45
- companyId: payload.companyId,
46
- roles: payload.roles || [],
47
- permissions: payload.permissions || [],
48
- isSuperAdmin: payload.isSuperAdmin || false,
49
- };
50
- return next();
51
- }
52
- catch {
53
- // Fall through to 401
54
- }
55
- }
56
- }
57
- _res.status(401).json({ success: false, message: 'Authentication required' });
66
+ res.status(401).json({ success: false, message: 'Authentication required' });
58
67
  };
59
68
  }
60
69
  /**
61
- * Optional auth — attaches user if present, continues if not.
70
+ * Optional auth — attaches user if present (and trusted), continues if not.
62
71
  */
63
72
  export function optionalAuthFromGateway(jwtSecret) {
64
73
  return (req, _res, next) => {
65
- const userId = req.headers[GATEWAY_HEADERS.USER_ID];
66
- if (userId) {
67
- req.user = {
68
- id: userId,
69
- email: req.headers[GATEWAY_HEADERS.USER_EMAIL] || '',
70
- companyId: req.headers[GATEWAY_HEADERS.COMPANY_ID] || '',
71
- roles: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_ROLES]),
72
- permissions: parseArrayHeader(req.headers[GATEWAY_HEADERS.USER_PERMISSIONS]),
73
- isSuperAdmin: req.headers[GATEWAY_HEADERS.IS_SUPERADMIN] === 'true',
74
- };
75
- }
76
- else if (jwtSecret) {
77
- const token = extractBearerToken(req.headers.authorization);
78
- if (token) {
79
- try {
80
- const payload = verifyToken(token, jwtSecret);
81
- req.user = {
82
- id: payload.sub,
83
- email: payload.email,
84
- companyId: payload.companyId,
85
- roles: payload.roles || [],
86
- permissions: payload.permissions || [],
87
- isSuperAdmin: payload.isSuperAdmin || false,
88
- };
89
- }
90
- catch { /* ignore */ }
91
- }
92
- }
74
+ const user = userFromGatewayHeaders(req) ?? userFromBearerToken(req, jwtSecret);
75
+ if (user)
76
+ req.user = user;
93
77
  next();
94
78
  };
95
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.middleware.js","sourceRoot":"","sources":["../../src/express/auth.middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.middleware.js","sourceRoot":"","sources":["../../src/express/auth.middleware.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import winston from 'winston';
2
+ export { redactFormat, redactSensitive, isSensitiveKey, REDACTED } from './redact.js';
2
3
  export declare function createLogger(service: string, level?: string): winston.Logger;
3
4
  export declare function createAuditLogger(service: string): winston.Logger;
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAmG9B,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAwB5E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAiBjE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgGtF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAyB5E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAiBjE"}
@@ -2,6 +2,8 @@ import winston from 'winston';
2
2
  import DailyRotateFile from 'winston-daily-rotate-file';
3
3
  import { mkdirSync } from 'fs';
4
4
  import { resolve } from 'path';
5
+ import { redactFormat } from './redact.js';
6
+ export { redactFormat, redactSensitive, isSensitiveKey, REDACTED } from './redact.js';
5
7
  const { combine, timestamp, json, errors, colorize, printf, splat } = winston.format;
6
8
  /**
7
9
  * Custom dev console format that renders meta cleanly and warns when callers
@@ -101,7 +103,8 @@ export function createLogger(service, level) {
101
103
  return winston.createLogger({
102
104
  level: resolvedLevel,
103
105
  defaultMeta: { service },
104
- format: combine(errors({ stack: true }), splat(), timestamp()),
106
+ // redactFormat runs after splat so metadata passed as extra arguments is covered too.
107
+ format: combine(errors({ stack: true }), splat(), redactFormat(), timestamp()),
105
108
  transports,
106
109
  });
107
110
  }
@@ -118,7 +121,7 @@ export function createAuditLogger(service) {
118
121
  return winston.createLogger({
119
122
  level: 'info',
120
123
  defaultMeta: { service, type: 'audit' },
121
- format: combine(splat(), timestamp(), json()),
124
+ format: combine(splat(), redactFormat(), timestamp(), json()),
122
125
  transports,
123
126
  });
124
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import winston from 'winston';
2
+ export declare const REDACTED = "[REDACTED]";
3
+ /** True for keys whose values are redacted (case/separator-insensitive). */
4
+ export declare function isSensitiveKey(key: string): boolean;
5
+ /**
6
+ * Deep copy of `value` with sensitive keys replaced by [REDACTED] and inline
7
+ * bearer/basic credentials masked. Errors keep their message and stack.
8
+ * Handles cycles and caps depth.
9
+ */
10
+ export declare function redactSensitive(value: unknown, depth?: number, seen?: WeakSet<object>): unknown;
11
+ /**
12
+ * Winston format that redacts every log entry's message and metadata in place.
13
+ * Winston's internal Symbol keys (level/message/splat) are left untouched.
14
+ */
15
+ export declare const redactFormat: winston.Logform.FormatWrap;
16
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/logging/redact.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,eAAO,MAAM,QAAQ,eAAe,CAAC;AA4BrC,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKnD;AASD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,EAAE,IAAI,GAAE,OAAO,CAAC,MAAM,CAAiB,GAAG,OAAO,CAqBzG;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,4BAMvB,CAAC"}
@@ -0,0 +1,83 @@
1
+ import winston from 'winston';
2
+ export const REDACTED = '[REDACTED]';
3
+ // Exact keys (compared lower-cased, with '-' and '_' removed) and key fragments
4
+ // whose values must never reach a log: credentials, tokens, OTPs, secrets.
5
+ const EXACT_KEYS = new Set([
6
+ 'authorization',
7
+ 'proxyauthorization',
8
+ 'cookie',
9
+ 'setcookie',
10
+ 'password',
11
+ 'passwd',
12
+ 'currentpassword',
13
+ 'newpassword',
14
+ 'apikey',
15
+ 'otp',
16
+ 'pin',
17
+ 'smtppassword',
18
+ 'encryptionkey',
19
+ 'privatekey',
20
+ 'xinternalservicesecret',
21
+ 'xgatewaysignature',
22
+ ]);
23
+ const KEY_FRAGMENTS = ['secret', 'password', 'passphrase', 'credential'];
24
+ // accessToken, refresh_token, captchaToken… but not counters like promptTokens.
25
+ const KEY_SUFFIXES = ['token'];
26
+ const MAX_DEPTH = 8;
27
+ /** True for keys whose values are redacted (case/separator-insensitive). */
28
+ export function isSensitiveKey(key) {
29
+ const normalized = key.toLowerCase().replace(/[-_]/g, '');
30
+ return EXACT_KEYS.has(normalized)
31
+ || KEY_FRAGMENTS.some((fragment) => normalized.includes(fragment))
32
+ || KEY_SUFFIXES.some((suffix) => normalized.endsWith(suffix));
33
+ }
34
+ // Bearer/Basic credentials embedded in free text (e.g. a logged header line or error message).
35
+ const INLINE_CREDENTIAL = /\b(Bearer|Basic)\s+[A-Za-z0-9\-._~+/]+=*/g;
36
+ function redactString(value) {
37
+ return value.replace(INLINE_CREDENTIAL, `$1 ${REDACTED}`);
38
+ }
39
+ /**
40
+ * Deep copy of `value` with sensitive keys replaced by [REDACTED] and inline
41
+ * bearer/basic credentials masked. Errors keep their message and stack.
42
+ * Handles cycles and caps depth.
43
+ */
44
+ export function redactSensitive(value, depth = 0, seen = new WeakSet()) {
45
+ if (typeof value === 'string')
46
+ return redactString(value);
47
+ if (value === null || typeof value !== 'object')
48
+ return value;
49
+ if (depth >= MAX_DEPTH)
50
+ return '[Truncated]';
51
+ if (seen.has(value))
52
+ return '[Circular]';
53
+ seen.add(value);
54
+ if (Array.isArray(value))
55
+ return value.map((item) => redactSensitive(item, depth + 1, seen));
56
+ if (value instanceof Date || Buffer.isBuffer(value))
57
+ return value;
58
+ const source = value;
59
+ const result = {};
60
+ if (value instanceof Error) {
61
+ result.name = value.name;
62
+ result.message = redactString(value.message);
63
+ if (value.stack)
64
+ result.stack = redactString(value.stack);
65
+ }
66
+ for (const key of Object.keys(source)) {
67
+ result[key] = isSensitiveKey(key) ? REDACTED : redactSensitive(source[key], depth + 1, seen);
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Winston format that redacts every log entry's message and metadata in place.
73
+ * Winston's internal Symbol keys (level/message/splat) are left untouched.
74
+ */
75
+ export const redactFormat = winston.format((info) => {
76
+ for (const key of Object.keys(info)) {
77
+ if (key === 'level')
78
+ continue;
79
+ info[key] = isSensitiveKey(key) ? REDACTED : redactSensitive(info[key]);
80
+ }
81
+ return info;
82
+ });
83
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/logging/redact.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { CanActivate, ExecutionContext } from '@nestjs/common';
2
2
  import { Reflector } from '@nestjs/core';
3
3
  export declare const IS_PUBLIC_KEY = "isPublic";
4
+ /** Request property AuthGuard sets when the caller came from signed gateway headers. */
5
+ export declare const GATEWAY_VERIFIED_FLAG = "gatewayVerified";
4
6
  /**
5
7
  * NestJS Guard: validates JWT or trusts gateway-injected headers.
6
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../../src/nestjs/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAczC,eAAO,MAAM,aAAa,aAAa,CAAC;AAExC;;GAEG;AACH,qBACa,SAAU,YAAW,WAAW;IAC/B,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAElC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CA8C/D"}
1
+ {"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../../src/nestjs/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAezC,eAAO,MAAM,aAAa,aAAa,CAAC;AAExC,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD;;GAEG;AACH,qBACa,SAAU,YAAW,WAAW;IAC/B,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAElC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAmD/D"}
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  import { Injectable, UnauthorizedException, } from '@nestjs/common';
11
11
  import { Reflector } from '@nestjs/core';
12
12
  import { verifyToken } from '../common/jwt.utils.js';
13
+ import { isTrustedGatewayIdentity, isDirectJwtFallbackAllowed } from '../common/gateway-signature.js';
13
14
  import { GATEWAY_HEADERS } from '../types/index.js';
14
15
  /** Parse a header value that may be a JSON array string or comma-separated. */
15
16
  function parseArrayHeader(value) {
@@ -25,6 +26,8 @@ function parseArrayHeader(value) {
25
26
  return trimmed.split(',').filter(Boolean);
26
27
  }
27
28
  export const IS_PUBLIC_KEY = 'isPublic';
29
+ /** Request property AuthGuard sets when the caller came from signed gateway headers. */
30
+ export const GATEWAY_VERIFIED_FLAG = 'gatewayVerified';
28
31
  /**
29
32
  * NestJS Guard: validates JWT or trusts gateway-injected headers.
30
33
  */
@@ -41,9 +44,10 @@ let AuthGuard = class AuthGuard {
41
44
  if (isPublic)
42
45
  return true;
43
46
  const request = context.switchToHttp().getRequest();
44
- // Trust gateway-injected headers first
47
+ // Trust gateway-injected headers only with a valid gateway signature
45
48
  const gatewayUserId = request.headers[GATEWAY_HEADERS.USER_ID];
46
- if (gatewayUserId) {
49
+ if (gatewayUserId && isTrustedGatewayIdentity(request.headers)) {
50
+ request[GATEWAY_VERIFIED_FLAG] = true;
47
51
  request.user = {
48
52
  id: gatewayUserId,
49
53
  companyId: request.headers[GATEWAY_HEADERS.COMPANY_ID] || undefined,
@@ -54,7 +58,11 @@ let AuthGuard = class AuthGuard {
54
58
  };
55
59
  return true;
56
60
  }
57
- // Fallback to direct JWT validation
61
+ // Fallback to direct JWT validation — development only; production
62
+ // requests must arrive through the gateway.
63
+ if (!isDirectJwtFallbackAllowed()) {
64
+ throw new UnauthorizedException('Authentication required');
65
+ }
58
66
  const authHeader = request.headers.authorization;
59
67
  if (!authHeader?.startsWith('Bearer ')) {
60
68
  throw new UnauthorizedException('Missing authentication token');
@@ -1 +1 @@
1
- {"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/nestjs/auth.guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/nestjs/auth.guard.ts"],"names":[],"mappings":"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"}