@oxyhq/core 3.10.1 → 3.11.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 (82) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/AuthManager.js +9 -2
  3. package/dist/cjs/HttpService.js +27 -9
  4. package/dist/cjs/OxyServices.base.js +3 -2
  5. package/dist/cjs/crypto/canonicalJson.js +107 -0
  6. package/dist/cjs/crypto/keyManager.js +67 -8
  7. package/dist/cjs/crypto/signatureService.js +103 -0
  8. package/dist/cjs/index.js +15 -4
  9. package/dist/cjs/mixins/OxyServices.assets.js +16 -1
  10. package/dist/cjs/mixins/OxyServices.auth.js +190 -1
  11. package/dist/cjs/mixins/OxyServices.identity.js +291 -0
  12. package/dist/cjs/mixins/OxyServices.sso.js +28 -1
  13. package/dist/cjs/mixins/OxyServices.user.js +1 -0
  14. package/dist/cjs/mixins/index.js +3 -0
  15. package/dist/cjs/server/cors.js +20 -21
  16. package/dist/cjs/server/rateLimit.js +32 -8
  17. package/dist/cjs/utils/ssoReturn.js +1 -1
  18. package/dist/esm/.tsbuildinfo +1 -1
  19. package/dist/esm/AuthManager.js +9 -2
  20. package/dist/esm/HttpService.js +27 -9
  21. package/dist/esm/OxyServices.base.js +3 -2
  22. package/dist/esm/crypto/canonicalJson.js +104 -0
  23. package/dist/esm/crypto/keyManager.js +67 -8
  24. package/dist/esm/crypto/signatureService.js +102 -0
  25. package/dist/esm/index.js +9 -1
  26. package/dist/esm/mixins/OxyServices.assets.js +16 -1
  27. package/dist/esm/mixins/OxyServices.auth.js +190 -1
  28. package/dist/esm/mixins/OxyServices.identity.js +287 -0
  29. package/dist/esm/mixins/OxyServices.sso.js +28 -1
  30. package/dist/esm/mixins/OxyServices.user.js +1 -0
  31. package/dist/esm/mixins/index.js +3 -0
  32. package/dist/esm/server/cors.js +20 -21
  33. package/dist/esm/server/rateLimit.js +32 -8
  34. package/dist/esm/utils/ssoReturn.js +1 -1
  35. package/dist/types/.tsbuildinfo +1 -1
  36. package/dist/types/HttpService.d.ts +3 -0
  37. package/dist/types/OxyServices.d.ts +2 -2
  38. package/dist/types/crypto/canonicalJson.d.ts +44 -0
  39. package/dist/types/crypto/keyManager.d.ts +7 -0
  40. package/dist/types/crypto/signatureService.d.ts +61 -0
  41. package/dist/types/index.d.ts +6 -2
  42. package/dist/types/mixins/OxyServices.auth.d.ts +136 -0
  43. package/dist/types/mixins/OxyServices.identity.d.ts +249 -0
  44. package/dist/types/mixins/OxyServices.sso.d.ts +4 -1
  45. package/dist/types/mixins/index.d.ts +2 -1
  46. package/dist/types/models/interfaces.d.ts +3 -0
  47. package/dist/types/server/cors.d.ts +5 -5
  48. package/dist/types/utils/ssoReturn.d.ts +1 -1
  49. package/package.json +2 -2
  50. package/src/AuthManager.ts +8 -2
  51. package/src/HttpService.ts +36 -8
  52. package/src/OxyServices.base.ts +3 -2
  53. package/src/OxyServices.ts +1 -1
  54. package/src/__tests__/authManager.security.test.ts +31 -0
  55. package/src/__tests__/httpServiceCsrf.test.ts +75 -0
  56. package/src/crypto/__tests__/canonicalJson.test.ts +116 -0
  57. package/src/crypto/__tests__/keyManager.atomicity.test.ts +41 -2
  58. package/src/crypto/__tests__/signChallengeShared.test.ts +64 -0
  59. package/src/crypto/__tests__/signedRecord.test.ts +125 -0
  60. package/src/crypto/canonicalJson.ts +120 -0
  61. package/src/crypto/keyManager.ts +62 -12
  62. package/src/crypto/signatureService.ts +126 -0
  63. package/src/index.ts +27 -2
  64. package/src/mixins/OxyServices.assets.ts +16 -1
  65. package/src/mixins/OxyServices.auth.ts +309 -1
  66. package/src/mixins/OxyServices.identity.ts +445 -0
  67. package/src/mixins/OxyServices.sso.ts +30 -1
  68. package/src/mixins/OxyServices.user.ts +1 -0
  69. package/src/mixins/__tests__/OxyServices.identity.test.ts +364 -0
  70. package/src/mixins/__tests__/assetCredentials.test.ts +47 -0
  71. package/src/mixins/__tests__/commonsSignIn.test.ts +277 -0
  72. package/src/mixins/__tests__/serviceAuth.test.ts +19 -0
  73. package/src/mixins/__tests__/sso.test.ts +31 -0
  74. package/src/mixins/index.ts +4 -0
  75. package/src/models/interfaces.ts +3 -0
  76. package/src/server/__tests__/cors.test.ts +5 -1
  77. package/src/server/__tests__/rateLimit.test.ts +116 -0
  78. package/src/server/cors.ts +25 -20
  79. package/src/server/rateLimit.ts +39 -8
  80. package/src/utils/__tests__/consumeSsoReturn.test.ts +1 -1
  81. package/src/utils/__tests__/ssoReturn.test.ts +1 -1
  82. package/src/utils/ssoReturn.ts +2 -2
@@ -25,12 +25,36 @@ function isBuiltInExempt(req) {
25
25
  function ipKeyGenerator(ip) {
26
26
  return ip.replace(/:/g, '_');
27
27
  }
28
- /** Resolve the rate-limit key: per authenticated user, else per (IPv6-safe) IP. */
29
- function resolveKey(req) {
28
+ /**
29
+ * Resolve the trusted authenticated rate-limit key.
30
+ *
31
+ * `oxy.auth({ optional: true })` preserves legacy non-session user tokens by
32
+ * decoding their JWT claims locally. Those claims are not cryptographically
33
+ * verified and therefore MUST NOT influence abuse-control buckets. Only use
34
+ * identities that came from a server-validated session or a verified service
35
+ * token/delegation.
36
+ */
37
+ function resolveTrustedAuthenticatedKey(req) {
30
38
  const userId = req.userId ?? req.user?.id ?? req.user?._id;
31
- if (userId) {
39
+ if (userId && req.sessionId) {
32
40
  return `user:${userId}`;
33
41
  }
42
+ const delegatedUserId = req.serviceActingAs?.userId;
43
+ if (delegatedUserId && req.serviceApp?.appId) {
44
+ return `user:${delegatedUserId}`;
45
+ }
46
+ const serviceAppId = req.serviceApp?.appId;
47
+ if (serviceAppId) {
48
+ return `service:${serviceAppId}`;
49
+ }
50
+ return null;
51
+ }
52
+ /** Resolve the rate-limit key: per trusted authenticated identity, else per (IPv6-safe) IP. */
53
+ function resolveKey(req) {
54
+ const authenticatedKey = resolveTrustedAuthenticatedKey(req);
55
+ if (authenticatedKey) {
56
+ return authenticatedKey;
57
+ }
34
58
  const ip = req.ip || req.socket.remoteAddress || 'unknown';
35
59
  return ipKeyGenerator(ip);
36
60
  }
@@ -47,9 +71,9 @@ function createOxyRateLimit(oxy, options = {}) {
47
71
  windowMs,
48
72
  ...(store ? { store } : {}),
49
73
  max: (req) => {
50
- const authed = req;
51
- const userId = authed.userId ?? authed.user?.id ?? authed.user?._id;
52
- return userId ? authenticatedMax : anonymousMax;
74
+ return resolveTrustedAuthenticatedKey(req)
75
+ ? authenticatedMax
76
+ : anonymousMax;
53
77
  },
54
78
  keyGenerator: (req) => resolveKey(req),
55
79
  message,
@@ -67,8 +91,8 @@ function createOxyRateLimit(oxy, options = {}) {
67
91
  resolveSession(req, res, (err) => {
68
92
  if (err) {
69
93
  // Optional auth never rejects; a token error just means "anonymous".
70
- // Swallow the error and continue to limit as anonymous.
71
- next();
94
+ // Swallow the error and continue through the anonymous limiter.
95
+ limiter(req, res, next);
72
96
  return;
73
97
  }
74
98
  limiter(req, res, next);
@@ -241,7 +241,7 @@ async function consumeSsoReturn(oxy, deps = {}) {
241
241
  }
242
242
  let session;
243
243
  try {
244
- session = await oxy.exchangeSsoCode(ret.code);
244
+ session = await oxy.exchangeSsoCode(ret.code, ret.state);
245
245
  }
246
246
  catch (error) {
247
247
  onExchangeError?.(error);