@prosopo/provider 4.12.0 → 4.13.1

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 (228) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +43 -39
  2. package/.turbo/turbo-build$colon$tsc.log +24 -24
  3. package/.turbo/turbo-build.log +43 -40
  4. package/CHANGELOG.md +97 -0
  5. package/dist/api/admin/apiClearAllCountersEndpoint.d.ts.map +1 -1
  6. package/dist/api/admin/apiClearAllCountersEndpoint.js +1 -1
  7. package/dist/api/admin/apiClearAllCountersEndpoint.js.map +1 -1
  8. package/dist/api/admin/apiDnsEventEndpoint.d.ts.map +1 -1
  9. package/dist/api/admin/apiDnsEventEndpoint.js +1 -1
  10. package/dist/api/admin/apiDnsEventEndpoint.js.map +1 -1
  11. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.d.ts.map +1 -1
  12. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +1 -1
  13. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js.map +1 -1
  14. package/dist/api/admin/apiGetDecisionMachineEndpoint.d.ts.map +1 -1
  15. package/dist/api/admin/apiGetDecisionMachineEndpoint.js +1 -1
  16. package/dist/api/admin/apiGetDecisionMachineEndpoint.js.map +1 -1
  17. package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts.map +1 -1
  18. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +1 -1
  19. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js.map +1 -1
  20. package/dist/api/admin/apiRegisterSiteKeysEndpoint.d.ts.map +1 -1
  21. package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +1 -1
  22. package/dist/api/admin/apiRegisterSiteKeysEndpoint.js.map +1 -1
  23. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.d.ts.map +1 -1
  24. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +1 -1
  25. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js.map +1 -1
  26. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.d.ts.map +1 -1
  27. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +1 -1
  28. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js.map +1 -1
  29. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
  30. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +1 -2
  31. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js.map +1 -1
  32. package/dist/api/admin/apiRemoveSiteKeyEndpoint.d.ts.map +1 -1
  33. package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +1 -1
  34. package/dist/api/admin/apiRemoveSiteKeyEndpoint.js.map +1 -1
  35. package/dist/api/admin/apiRemoveSiteKeysEndpoint.d.ts.map +1 -1
  36. package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +1 -1
  37. package/dist/api/admin/apiRemoveSiteKeysEndpoint.js.map +1 -1
  38. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts.map +1 -1
  39. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +3 -1
  40. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js.map +1 -1
  41. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.d.ts.map +1 -1
  42. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +1 -1
  43. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js.map +1 -1
  44. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +1 -2
  45. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js.map +1 -1
  46. package/dist/api/blacklistRequestInspector.d.ts.map +1 -1
  47. package/dist/api/blacklistRequestInspector.js +7 -3
  48. package/dist/api/blacklistRequestInspector.js.map +1 -1
  49. package/dist/api/captcha/checkSpamEmail.d.ts.map +1 -1
  50. package/dist/api/captcha/checkSpamEmail.js +19 -4
  51. package/dist/api/captcha/checkSpamEmail.js.map +1 -1
  52. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.d.ts +0 -1
  53. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.d.ts.map +1 -1
  54. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +1 -7
  55. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js.map +1 -1
  56. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.d.ts.map +1 -1
  57. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +8 -7
  58. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js.map +1 -1
  59. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts +1 -1
  60. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
  61. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +68 -28
  62. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
  63. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts +0 -1
  64. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts.map +1 -1
  65. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +0 -1
  66. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js.map +1 -1
  67. package/dist/api/captcha/getImageCaptchaChallenge.d.ts.map +1 -1
  68. package/dist/api/captcha/getImageCaptchaChallenge.js +3 -0
  69. package/dist/api/captcha/getImageCaptchaChallenge.js.map +1 -1
  70. package/dist/api/captcha/getPoWCaptchaChallenge.d.ts.map +1 -1
  71. package/dist/api/captcha/getPoWCaptchaChallenge.js +3 -0
  72. package/dist/api/captcha/getPoWCaptchaChallenge.js.map +1 -1
  73. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
  74. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +3 -0
  75. package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
  76. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts +8 -0
  77. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
  78. package/dist/api/captcha/submitPoWCaptchaSolution.js +7 -0
  79. package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
  80. package/dist/api/captcha.d.ts +2 -1
  81. package/dist/api/captcha.d.ts.map +1 -1
  82. package/dist/api/captcha.js +12 -15
  83. package/dist/api/captcha.js.map +1 -1
  84. package/dist/api/domainMiddleware.d.ts.map +1 -1
  85. package/dist/api/domainMiddleware.js +4 -0
  86. package/dist/api/domainMiddleware.js.map +1 -1
  87. package/dist/api/forwardVerify.d.ts +14 -0
  88. package/dist/api/forwardVerify.d.ts.map +1 -0
  89. package/dist/api/forwardVerify.js +54 -0
  90. package/dist/api/forwardVerify.js.map +1 -0
  91. package/dist/api/headerCheckMiddleware.d.ts.map +1 -1
  92. package/dist/api/headerCheckMiddleware.js +7 -4
  93. package/dist/api/headerCheckMiddleware.js.map +1 -1
  94. package/dist/api/ja4.d.ts +5 -0
  95. package/dist/api/ja4.d.ts.map +1 -0
  96. package/dist/api/ja4.js +203 -0
  97. package/dist/api/ja4.js.map +1 -0
  98. package/dist/api/ja4Middleware.d.ts.map +1 -1
  99. package/dist/api/ja4Middleware.js +9 -18
  100. package/dist/api/ja4Middleware.js.map +1 -1
  101. package/dist/api/metrics.d.ts +40 -0
  102. package/dist/api/metrics.d.ts.map +1 -0
  103. package/dist/api/metrics.js +260 -0
  104. package/dist/api/metrics.js.map +1 -0
  105. package/dist/api/public.d.ts.map +1 -1
  106. package/dist/api/public.js +4 -0
  107. package/dist/api/public.js.map +1 -1
  108. package/dist/api/startProviderApi.d.ts.map +1 -1
  109. package/dist/api/startProviderApi.js +3 -1
  110. package/dist/api/startProviderApi.js.map +1 -1
  111. package/dist/api/verify.d.ts.map +1 -1
  112. package/dist/api/verify.js +85 -8
  113. package/dist/api/verify.js.map +1 -1
  114. package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +1 -1
  115. package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +1 -2
  116. package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +1 -1
  117. package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +1 -1
  118. package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +1 -2
  119. package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +1 -2
  120. package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +1 -1
  121. package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +1 -1
  122. package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +1 -3
  123. package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +1 -2
  124. package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +1 -2
  125. package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +3 -2
  126. package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +1 -1
  127. package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +1 -2
  128. package/dist/cjs/api/blacklistRequestInspector.cjs +7 -3
  129. package/dist/cjs/api/captcha/checkSpamEmail.cjs +18 -3
  130. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +1 -7
  131. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +8 -7
  132. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +70 -30
  133. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +0 -1
  134. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +3 -0
  135. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +3 -0
  136. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +3 -0
  137. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +9 -1
  138. package/dist/cjs/api/captcha.cjs +12 -15
  139. package/dist/cjs/api/domainMiddleware.cjs +4 -0
  140. package/dist/cjs/api/forwardVerify.cjs +54 -0
  141. package/dist/cjs/api/headerCheckMiddleware.cjs +7 -4
  142. package/dist/cjs/api/ja4.cjs +203 -0
  143. package/dist/cjs/api/ja4Middleware.cjs +11 -21
  144. package/dist/cjs/api/metrics.cjs +260 -0
  145. package/dist/cjs/api/public.cjs +4 -0
  146. package/dist/cjs/api/startProviderApi.cjs +3 -1
  147. package/dist/cjs/api/verify.cjs +83 -6
  148. package/dist/cjs/index.cjs +1 -0
  149. package/dist/cjs/tasks/captchaManager.cjs +23 -3
  150. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +20 -22
  151. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +17 -23
  152. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +15 -21
  153. package/dist/index.js +2 -1
  154. package/dist/tasks/captchaManager.d.ts.map +1 -1
  155. package/dist/tasks/captchaManager.js +23 -2
  156. package/dist/tasks/captchaManager.js.map +1 -1
  157. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  158. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +20 -22
  159. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  160. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  161. package/dist/tasks/powCaptcha/powTasks.js +17 -23
  162. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  163. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
  164. package/dist/tasks/puzzleCaptcha/puzzleTasks.js +15 -21
  165. package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
  166. package/dist/tests/unit/api/admin/apiClearAllCountersEndpoint.unit.test.js +1 -0
  167. package/dist/tests/unit/api/admin/apiClearAllCountersEndpoint.unit.test.js.map +1 -1
  168. package/dist/tests/unit/api/admin/apiDnsEventEndpoint.unit.test.js +5 -1
  169. package/dist/tests/unit/api/admin/apiDnsEventEndpoint.unit.test.js.map +1 -1
  170. package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js +1 -0
  171. package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js.map +1 -1
  172. package/dist/tests/unit/api/admin/apiRegisterSiteKeysEndpoint.unit.test.js +1 -0
  173. package/dist/tests/unit/api/admin/apiRegisterSiteKeysEndpoint.unit.test.js.map +1 -1
  174. package/dist/tests/unit/api/admin/apiRemoveDetectorKeyEndpoint.unit.test.js +1 -0
  175. package/dist/tests/unit/api/admin/apiRemoveDetectorKeyEndpoint.unit.test.js.map +1 -1
  176. package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js +1 -0
  177. package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js.map +1 -1
  178. package/dist/tests/unit/api/admin/apiUpdateDetectorKeyEndpoint.unit.test.js +1 -0
  179. package/dist/tests/unit/api/admin/apiUpdateDetectorKeyEndpoint.unit.test.js.map +1 -1
  180. package/dist/tests/unit/api/adminRoutes.unit.test.js +1 -0
  181. package/dist/tests/unit/api/adminRoutes.unit.test.js.map +1 -1
  182. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js +43 -0
  183. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js.map +1 -1
  184. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.d.ts +2 -0
  185. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.d.ts.map +1 -0
  186. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js +62 -0
  187. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js.map +1 -0
  188. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.unit.test.js +0 -1
  189. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.unit.test.js.map +1 -1
  190. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.unit.test.js +0 -1
  191. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.unit.test.js.map +1 -1
  192. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.d.ts +2 -0
  193. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.d.ts.map +1 -0
  194. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js +130 -0
  195. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js.map +1 -0
  196. package/dist/tests/unit/api/captcha.unit.test.js +31 -1
  197. package/dist/tests/unit/api/captcha.unit.test.js.map +1 -1
  198. package/dist/tests/unit/api/forwardVerify.unit.test.d.ts +2 -0
  199. package/dist/tests/unit/api/forwardVerify.unit.test.d.ts.map +1 -0
  200. package/dist/tests/unit/api/forwardVerify.unit.test.js +151 -0
  201. package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -0
  202. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +68 -0
  203. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  204. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js +2 -2
  205. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js.map +1 -1
  206. package/dist/tests/unit/api/ja4.unit.test.d.ts +2 -0
  207. package/dist/tests/unit/api/ja4.unit.test.d.ts.map +1 -0
  208. package/dist/tests/unit/api/ja4.unit.test.js +233 -0
  209. package/dist/tests/unit/api/ja4.unit.test.js.map +1 -0
  210. package/dist/tests/unit/api/ja4Middleware.unit.test.js +11 -8
  211. package/dist/tests/unit/api/ja4Middleware.unit.test.js.map +1 -1
  212. package/dist/tests/unit/api/public.unit.test.js +72 -0
  213. package/dist/tests/unit/api/public.unit.test.js.map +1 -1
  214. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +1 -1
  215. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
  216. package/dist/tests/unit/schedulers/getClientList.unit.test.js +1 -1
  217. package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
  218. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +1 -1
  219. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
  220. package/dist/tests/unit/tasks/captchaManager.unit.test.js +87 -2
  221. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
  222. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +1 -1
  223. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
  224. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js +1 -1
  225. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js.map +1 -1
  226. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +4 -1
  227. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +1 -1
  228. package/package.json +23 -23
@@ -7,6 +7,7 @@ require("../../tasks/index.cjs");
7
7
  const normalizeRequestIp = require("../../utils/normalizeRequestIp.cjs");
8
8
  const apiToggleMaintenanceModeEndpoint = require("../admin/apiToggleMaintenanceModeEndpoint.cjs");
9
9
  const blacklistRequestInspector = require("../blacklistRequestInspector.cjs");
10
+ const metrics = require("../metrics.cjs");
10
11
  const validateAddress = require("../validateAddress.cjs");
11
12
  const maintenanceModeResponses = require("./maintenanceModeResponses.cjs");
12
13
  const tasks = require("../../tasks/tasks.cjs");
@@ -175,8 +176,10 @@ const getPoWCaptchaChallenge = (env, userAccessRulesStorage) => async (req, res,
175
176
  session: sessionId
176
177
  }
177
178
  }));
179
+ metrics.recordCaptchaIssued(types.CaptchaType.pow);
178
180
  return res.json(getPowCaptchaResponse);
179
181
  } catch (err) {
182
+ metrics.recordCaptchaIssueError(types.CaptchaType.pow);
180
183
  req.logger.error(() => ({
181
184
  err,
182
185
  body: req.body,
@@ -7,6 +7,7 @@ require("../../tasks/index.cjs");
7
7
  const normalizeRequestIp = require("../../utils/normalizeRequestIp.cjs");
8
8
  const apiToggleMaintenanceModeEndpoint = require("../admin/apiToggleMaintenanceModeEndpoint.cjs");
9
9
  const blacklistRequestInspector = require("../blacklistRequestInspector.cjs");
10
+ const metrics = require("../metrics.cjs");
10
11
  const validateAddress = require("../validateAddress.cjs");
11
12
  const maintenanceModeResponses = require("./maintenanceModeResponses.cjs");
12
13
  const tasks = require("../../tasks/tasks.cjs");
@@ -178,8 +179,10 @@ const getPuzzleCaptchaChallenge = (env, userAccessRulesStorage) => async (req, r
178
179
  session: sessionId
179
180
  }
180
181
  }));
182
+ metrics.recordCaptchaIssued(types.CaptchaType.puzzle);
181
183
  return res.json(getPuzzleCaptchaResponse);
182
184
  } catch (err) {
185
+ metrics.recordCaptchaIssueError(types.CaptchaType.puzzle);
183
186
  req.logger.error(() => ({
184
187
  err,
185
188
  body: req.body,
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
2
3
  const common = require("@prosopo/common");
3
4
  const types = require("@prosopo/types");
4
5
  const util = require("@prosopo/util");
@@ -177,9 +178,16 @@ const buildEscalation = async (tasks2, result, challenge) => {
177
178
  originSession.mode,
178
179
  originSession.simdReadings
179
180
  );
181
+ if (tasks2.writeQueue) {
182
+ await tasks2.writeQueue.cacheSessionEscalation(
183
+ powRecord.sessionId,
184
+ newSession.sessionId
185
+ );
186
+ }
180
187
  return {
181
188
  captchaType: routed.captchaType,
182
189
  sessionId: newSession.sessionId
183
190
  };
184
191
  };
185
- module.exports = submitPoWCaptchaSolution;
192
+ exports.buildEscalation = buildEscalation;
193
+ exports.default = submitPoWCaptchaSolution;
@@ -12,6 +12,9 @@ const submitImageCaptchaSolution = require("./captcha/submitImageCaptchaSolution
12
12
  const submitPoWCaptchaSolution = require("./captcha/submitPoWCaptchaSolution.cjs");
13
13
  const submitPuzzleCaptchaSolution = require("./captcha/submitPuzzleCaptchaSolution.cjs");
14
14
  const handler = require("./captcha/getFrictionlessCaptchaChallenge/handler.cjs");
15
+ const asyncHandler = (handler2) => (req, res, next) => {
16
+ Promise.resolve().then(() => handler2(req, res, next)).catch(next);
17
+ };
15
18
  function prosopoRouter(env) {
16
19
  const router = express.Router();
17
20
  let userAccessRulesStorage;
@@ -26,41 +29,35 @@ function prosopoRouter(env) {
26
29
  }
27
30
  router.post(
28
31
  types.ClientApiPaths.GetImageCaptchaChallenge,
29
- (req, res, next) => getImageCaptchaChallenge(env, userAccessRulesStorage)(req, res, next)
32
+ asyncHandler(getImageCaptchaChallenge(env, userAccessRulesStorage))
30
33
  );
31
34
  router.post(
32
35
  types.ClientApiPaths.SubmitImageCaptchaSolution,
33
- (req, res, next) => submitImageCaptchaSolution(env)(req, res, next)
36
+ asyncHandler(submitImageCaptchaSolution(env))
34
37
  );
35
38
  router.post(
36
39
  types.ClientApiPaths.GetPowCaptchaChallenge,
37
- (req, res, next) => getPoWCaptchaChallenge(env, userAccessRulesStorage)(req, res, next)
40
+ asyncHandler(getPoWCaptchaChallenge(env, userAccessRulesStorage))
38
41
  );
39
42
  router.post(
40
43
  types.ClientApiPaths.SubmitPowCaptchaSolution,
41
- (req, res, next) => submitPoWCaptchaSolution(env)(req, res, next)
44
+ asyncHandler(submitPoWCaptchaSolution.default(env))
42
45
  );
43
46
  router.post(
44
47
  types.ClientApiPaths.GetFrictionlessCaptchaChallenge,
45
- (req, res, next) => handler(env, userAccessRulesStorage)(
46
- req,
47
- res,
48
- next
49
- )
48
+ asyncHandler(handler(env, userAccessRulesStorage))
50
49
  );
51
50
  router.post(
52
51
  types.ClientApiPaths.GetPuzzleCaptchaChallenge,
53
- (req, res, next) => getPuzzleCaptchaChallenge(env, userAccessRulesStorage)(req, res, next)
52
+ asyncHandler(getPuzzleCaptchaChallenge(env, userAccessRulesStorage))
54
53
  );
55
54
  router.post(
56
55
  types.ClientApiPaths.SubmitPuzzleCaptchaSolution,
57
- (req, res, next) => submitPuzzleCaptchaSolution(env)(req, res, next)
58
- );
59
- router.post(
60
- types.ClientApiPaths.CheckSpamEmail,
61
- (req, res, next) => checkSpamEmail(env)(req, res, next)
56
+ asyncHandler(submitPuzzleCaptchaSolution(env))
62
57
  );
58
+ router.post(types.ClientApiPaths.CheckSpamEmail, asyncHandler(checkSpamEmail(env)));
63
59
  router.use(apiExpressRouter.handleErrors);
64
60
  return router;
65
61
  }
62
+ exports.asyncHandler = asyncHandler;
66
63
  exports.prosopoRouter = prosopoRouter;
@@ -7,6 +7,7 @@ const utilCrypto = require("@prosopo/util-crypto");
7
7
  const zod = require("zod");
8
8
  require("../tasks/index.cjs");
9
9
  const apiToggleMaintenanceModeEndpoint = require("./admin/apiToggleMaintenanceModeEndpoint.cjs");
10
+ const metrics = require("./metrics.cjs");
10
11
  const testSiteKey = require("./testSiteKey.cjs");
11
12
  const tasks = require("../tasks/tasks.cjs");
12
13
  const domainMiddleware = (env) => {
@@ -37,6 +38,7 @@ const domainMiddleware = (env) => {
37
38
  throw invalidSiteKeyError(req.i18n, siteKey, req.logger);
38
39
  }
39
40
  if (testSiteKey.isReservedTestSiteKey(siteKey)) {
41
+ metrics.recordDomainValidation("test_key");
40
42
  next();
41
43
  return;
42
44
  }
@@ -58,6 +60,7 @@ const domainMiddleware = (env) => {
58
60
  for (const candidate of candidateOrigins) {
59
61
  for (const domain of allowedDomains) {
60
62
  if (tasks$1.clientTaskManager.domainPatternMatcher(candidate, domain)) {
63
+ metrics.recordDomainValidation("allowed");
61
64
  next();
62
65
  return;
63
66
  }
@@ -65,6 +68,7 @@ const domainMiddleware = (env) => {
65
68
  }
66
69
  throw unauthorizedOriginError(req.i18n, origin, req.logger);
67
70
  } catch (err) {
71
+ metrics.recordDomainValidation("rejected");
68
72
  if (err instanceof common.ProsopoApiError || err instanceof zod.ZodError || err instanceof SyntaxError) {
69
73
  apiExpressRouter.handleErrors(err, req, res, next);
70
74
  } else {
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const api = require("@prosopo/api");
4
+ const loadBalancer = require("@prosopo/load-balancer");
5
+ function normalizeProviderUrl(url) {
6
+ try {
7
+ const parsed = new URL(url);
8
+ parsed.hostname = parsed.hostname.replace(/^(ipv4|ipv6)\./, "");
9
+ return parsed.toString().replace(/\/$/, "");
10
+ } catch {
11
+ return url.replace(/\/$/, "");
12
+ }
13
+ }
14
+ async function forwardVerifyIfNotIssuer(args) {
15
+ const { env, logger, path, providerUrl, dapp, user, body, alreadyForwarded } = args;
16
+ if (alreadyForwarded) {
17
+ return null;
18
+ }
19
+ if (!providerUrl) {
20
+ return null;
21
+ }
22
+ let providers;
23
+ try {
24
+ providers = await loadBalancer.getProviders(env.defaultEnvironment);
25
+ } catch (error) {
26
+ logger.warn(() => ({
27
+ msg: "Failed to load provider list; verifying locally",
28
+ err: error instanceof Error ? error : new Error(String(error)),
29
+ data: { providerUrl }
30
+ }));
31
+ return null;
32
+ }
33
+ const normalizedProviderUrl = normalizeProviderUrl(providerUrl);
34
+ const issuer = providers.find(
35
+ (provider) => normalizeProviderUrl(provider.url) === normalizedProviderUrl
36
+ );
37
+ if (!issuer) {
38
+ logger.warn(() => ({
39
+ msg: "Token providerUrl is not a known provider; verifying locally",
40
+ data: { providerUrl }
41
+ }));
42
+ return null;
43
+ }
44
+ if (env.pair?.address && issuer.address === env.pair.address) {
45
+ return null;
46
+ }
47
+ logger.info(() => ({
48
+ msg: "Forwarding verify request to issuing provider",
49
+ data: { providerUrl, path, dapp }
50
+ }));
51
+ const providerApi = new api.ProviderApi(issuer.url, dapp);
52
+ return providerApi.forwardVerify(path, body, user);
53
+ }
54
+ exports.forwardVerifyIfNotIssuer = forwardVerifyIfNotIssuer;
@@ -19,10 +19,13 @@ const headerCheckMiddleware = (env) => {
19
19
  validateAddress.validateAddr(user, void 0, req.logger);
20
20
  req.user = user;
21
21
  req.siteKey = siteKey;
22
- req.logger = req.logger.with({
23
- user,
24
- siteKey
25
- });
22
+ req.logger = req.logger.with(
23
+ {
24
+ user,
25
+ siteKey
26
+ },
27
+ "header-check"
28
+ );
26
29
  next();
27
30
  } catch (err) {
28
31
  return apiExpressRouter.handleErrors(err, req, res, next);
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const node_crypto = require("node:crypto");
4
+ const RECORD_HEADER_LENGTH = 5;
5
+ const HANDSHAKE_HEADER_LENGTH = 4;
6
+ const HANDSHAKE_RECORD_TYPE = 22;
7
+ const HANDSHAKE_MESSAGE_TYPE = 1;
8
+ const EXT_SERVER_NAME = 0;
9
+ const EXT_SIGNATURE_ALGORITHMS = 13;
10
+ const EXT_ALPN = 16;
11
+ const EXT_SUPPORTED_VERSIONS = 43;
12
+ function isGrease(id) {
13
+ return (id & 3855) === 2570 && id >> 8 === (id & 255);
14
+ }
15
+ function hash12(input) {
16
+ return node_crypto.createHash("sha256").update(input).digest("hex").slice(0, 12);
17
+ }
18
+ function formatIdList(ids) {
19
+ return ids.map((id) => id.toString(16).padStart(4, "0")).join(",");
20
+ }
21
+ function alpnChar(b) {
22
+ if (b >= 48 && b <= 57 || // 0-9
23
+ b >= 65 && b <= 90 || // A-Z
24
+ b >= 97 && b <= 122) {
25
+ return String.fromCharCode(b);
26
+ }
27
+ return b.toString(16).padStart(2, "0");
28
+ }
29
+ function alpnFirstLast(protocol) {
30
+ const first = protocol.length > 0 ? alpnChar(protocol.readUInt8(0)) : "0";
31
+ const last = protocol.length > 1 ? alpnChar(protocol.readUInt8(protocol.length - 1)) : "0";
32
+ return [first, last];
33
+ }
34
+ function tlsVersionStr(version) {
35
+ switch (version) {
36
+ case 769:
37
+ return "10";
38
+ case 770:
39
+ return "11";
40
+ case 771:
41
+ return "12";
42
+ case 772:
43
+ return "13";
44
+ default:
45
+ return "00";
46
+ }
47
+ }
48
+ class Ja4ParseError extends Error {
49
+ constructor(message) {
50
+ super(message);
51
+ this.name = "Ja4ParseError";
52
+ }
53
+ }
54
+ function calculateJa4(data) {
55
+ let offset = 0;
56
+ if (data.length < RECORD_HEADER_LENGTH + HANDSHAKE_HEADER_LENGTH) {
57
+ throw new Ja4ParseError("ClientHello too short");
58
+ }
59
+ const recordType = data.readUInt8(offset);
60
+ offset += 1;
61
+ if (recordType !== HANDSHAKE_RECORD_TYPE) {
62
+ throw new Ja4ParseError(
63
+ `Invalid record type: 0x${recordType.toString(16)}`
64
+ );
65
+ }
66
+ offset += 2;
67
+ const recordLen = data.readUInt16BE(offset);
68
+ offset += 2;
69
+ if (data.length < RECORD_HEADER_LENGTH + recordLen) {
70
+ throw new Ja4ParseError("Record length exceeds buffer");
71
+ }
72
+ data = data.subarray(0, RECORD_HEADER_LENGTH + recordLen);
73
+ if (data.length < RECORD_HEADER_LENGTH + HANDSHAKE_HEADER_LENGTH) {
74
+ throw new Ja4ParseError("Record too short for handshake header");
75
+ }
76
+ const msgType = data.readUInt8(offset);
77
+ offset += 1;
78
+ if (msgType !== HANDSHAKE_MESSAGE_TYPE) {
79
+ throw new Ja4ParseError(
80
+ `Not a ClientHello: handshake type 0x${msgType.toString(16)}`
81
+ );
82
+ }
83
+ const msgLen = data.readUIntBE(offset, 3);
84
+ offset += 3;
85
+ if (data.length - offset < msgLen) {
86
+ throw new Ja4ParseError("Handshake message length exceeds record");
87
+ }
88
+ data = data.subarray(0, offset + msgLen);
89
+ if (data.length - offset < 35) {
90
+ throw new Ja4ParseError("ClientHello body too short");
91
+ }
92
+ let clientVersion = data.readUInt16BE(offset);
93
+ offset += 2;
94
+ offset += 32;
95
+ const sessionIdLen = data.readUInt8(offset);
96
+ offset += 1;
97
+ if (data.length - offset < sessionIdLen) {
98
+ throw new Ja4ParseError("Truncated at session ID");
99
+ }
100
+ offset += sessionIdLen;
101
+ if (data.length - offset < 2) {
102
+ throw new Ja4ParseError("Truncated at cipher suites length");
103
+ }
104
+ const cipherSuitesLen = data.readUInt16BE(offset);
105
+ offset += 2;
106
+ if (data.length - offset < cipherSuitesLen) {
107
+ throw new Ja4ParseError("Truncated at cipher suites");
108
+ }
109
+ if (cipherSuitesLen % 2 !== 0) {
110
+ throw new Ja4ParseError("Cipher suites length is not a multiple of 2");
111
+ }
112
+ const cipherSuites = [];
113
+ for (let i = 0; i < cipherSuitesLen; i += 2) {
114
+ cipherSuites.push(data.readUInt16BE(offset + i));
115
+ }
116
+ offset += cipherSuitesLen;
117
+ if (data.length - offset < 1) {
118
+ throw new Ja4ParseError("Truncated at compression methods");
119
+ }
120
+ const compressionLen = data.readUInt8(offset);
121
+ offset += 1;
122
+ if (data.length - offset < compressionLen) {
123
+ throw new Ja4ParseError("Truncated at compression methods data");
124
+ }
125
+ offset += compressionLen;
126
+ if (data.length - offset < 2) {
127
+ throw new Ja4ParseError("Truncated at extensions length");
128
+ }
129
+ const extensionsLen = data.readUInt16BE(offset);
130
+ offset += 2;
131
+ if (data.length - offset < extensionsLen) {
132
+ throw new Ja4ParseError("Truncated at extensions");
133
+ }
134
+ const extIds = [];
135
+ const sigAlgorithms = [];
136
+ const alpnProtocols = [];
137
+ let extOffset = offset;
138
+ const extEnd = offset + extensionsLen;
139
+ while (extOffset + 4 <= extEnd) {
140
+ const extId = data.readUInt16BE(extOffset);
141
+ extOffset += 2;
142
+ const extLen = data.readUInt16BE(extOffset);
143
+ extOffset += 2;
144
+ if (extOffset + extLen > extEnd) break;
145
+ const extData = data.subarray(extOffset, extOffset + extLen);
146
+ extOffset += extLen;
147
+ extIds.push(extId);
148
+ if (extId === EXT_SUPPORTED_VERSIONS) {
149
+ if (extData.length >= 1) {
150
+ const listLen = extData.readUInt8(0);
151
+ let best = 0;
152
+ for (let i = 1; i + 1 < extData.length && i + 1 <= listLen; i += 2) {
153
+ const v = extData.readUInt16BE(i);
154
+ if (!isGrease(v) && v > best) best = v;
155
+ }
156
+ if (best > 0) clientVersion = best;
157
+ }
158
+ } else if (extId === EXT_SIGNATURE_ALGORITHMS) {
159
+ if (extData.length >= 2) {
160
+ const algLen = extData.readUInt16BE(0);
161
+ for (let i = 2; i + 1 < extData.length && i + 1 < algLen + 2; i += 2) {
162
+ const alg = extData.readUInt16BE(i);
163
+ if (!isGrease(alg)) sigAlgorithms.push(alg);
164
+ }
165
+ }
166
+ } else if (extId === EXT_ALPN) {
167
+ if (extData.length >= 2) {
168
+ const listLen = extData.readUInt16BE(0);
169
+ const listEnd = Math.min(extData.length, 2 + listLen);
170
+ let alpnOff = 2;
171
+ while (alpnOff < listEnd) {
172
+ const protoLen = extData.readUInt8(alpnOff);
173
+ alpnOff += 1;
174
+ if (alpnOff + protoLen > listEnd) break;
175
+ alpnProtocols.push(extData.subarray(alpnOff, alpnOff + protoLen));
176
+ alpnOff += protoLen;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ const versionStr = tlsVersionStr(clientVersion);
182
+ const sni = extIds.includes(EXT_SERVER_NAME) ? "d" : "i";
183
+ const firstAlpn = alpnProtocols[0];
184
+ const [alpnFirst, alpnLast] = firstAlpn ? alpnFirstLast(firstAlpn) : ["0", "0"];
185
+ const nonGreaseCiphers = cipherSuites.filter((c) => !isGrease(c));
186
+ const nonGreaseExts = extIds.filter((e) => !isGrease(e));
187
+ const cipherCount = Math.min(99, nonGreaseCiphers.length).toString().padStart(2, "0");
188
+ const extCount = Math.min(99, nonGreaseExts.length).toString().padStart(2, "0");
189
+ const firstChunk = `t${versionStr}${sni}${cipherCount}${extCount}${alpnFirst}${alpnLast}`;
190
+ const sortedCiphers = [...nonGreaseCiphers].sort((a, b) => a - b);
191
+ const cipherHash = hash12(formatIdList(sortedCiphers));
192
+ const filteredExts = nonGreaseExts.filter(
193
+ (e) => e !== EXT_SERVER_NAME && e !== EXT_ALPN
194
+ );
195
+ const sortedExts = [...filteredExts].sort((a, b) => a - b);
196
+ const extStr = formatIdList(sortedExts);
197
+ const sigAlgStr = formatIdList(sigAlgorithms);
198
+ const extHashInput = sigAlgStr.length > 0 ? `${extStr}_${sigAlgStr}` : extStr;
199
+ const extHash = hash12(extHashInput);
200
+ return `${firstChunk}_${cipherHash}_${extHash}`;
201
+ }
202
+ exports.Ja4ParseError = Ja4ParseError;
203
+ exports.calculateJa4 = calculateJa4;
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const node_stream = require("node:stream");
4
3
  const apiExpressRouter = require("@prosopo/api-express-router");
5
4
  const logger = require("@prosopo/logger");
6
5
  const utilCrypto = require("@prosopo/util-crypto");
7
- const readTlsClientHello = require("read-tls-client-hello");
8
- var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
6
+ const ja4 = require("./ja4.cjs");
9
7
  const DEFAULT_JA4 = "ja4";
10
8
  const getJA4 = async (headers, logger$1) => {
11
- logger$1 = logger$1 || logger.getLogger("info", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("api/ja4Middleware.cjs", document.baseURI).href);
9
+ logger$1 = logger$1 || logger.getLogger("info", "provider:ja4");
12
10
  if (process.env.NODE_ENV === "development") {
13
11
  return {
14
12
  ja4PlusFingerprint: `${DEFAULT_JA4}${utilCrypto.randomAsHex().slice(28, 32)}`
@@ -16,7 +14,6 @@ const getJA4 = async (headers, logger$1) => {
16
14
  }
17
15
  try {
18
16
  const xTlsClientHello = (headers["x-tls-clienthello"] || "").toString();
19
- const xTlsVersion = (headers["x-tls-version"] || "").toString().toLowerCase();
20
17
  const clientHelloBuffer = Buffer.from(xTlsClientHello, "base64");
21
18
  logger$1.debug(() => ({
22
19
  msg: "ClientHello First Bytes:",
@@ -28,17 +25,7 @@ const getJA4 = async (headers, logger$1) => {
28
25
  }));
29
26
  return { ja4PlusFingerprint: DEFAULT_JA4 };
30
27
  }
31
- logger$1.debug(() => ({
32
- msg: "Headers TLS Version:",
33
- data: { xTlsVersion }
34
- }));
35
- const readableStream = new node_stream.Readable({
36
- read() {
37
- this.push(clientHelloBuffer);
38
- }
39
- });
40
- const clientHello = await readTlsClientHello.readTlsClientHello(readableStream);
41
- const ja4PlusFingerprint = readTlsClientHello.calculateJa4FromHelloData(clientHello);
28
+ const ja4PlusFingerprint = ja4.calculateJa4(clientHelloBuffer);
42
29
  return { ja4PlusFingerprint };
43
30
  } catch (e) {
44
31
  logger$1.error(() => ({
@@ -52,11 +39,14 @@ const ja4Middleware = (env) => {
52
39
  return async (req, res, next) => {
53
40
  try {
54
41
  req.logger.debug(() => ({ data: { url: req.url } }));
55
- const ja4 = await getJA4(req.headers, req.logger);
56
- req.ja4 = ja4.ja4PlusFingerprint || "";
57
- req.logger = req.logger.with({
58
- ja4: req.ja4
59
- });
42
+ const ja42 = await getJA4(req.headers, req.logger);
43
+ req.ja4 = ja42.ja4PlusFingerprint || "";
44
+ req.logger = req.logger.with(
45
+ {
46
+ ja4: req.ja4
47
+ },
48
+ "ja4"
49
+ );
60
50
  next();
61
51
  } catch (err) {
62
52
  return apiExpressRouter.handleErrors(err, req, res, next);