@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.
- package/.turbo/turbo-build$colon$cjs.log +43 -39
- package/.turbo/turbo-build$colon$tsc.log +24 -24
- package/.turbo/turbo-build.log +43 -40
- package/CHANGELOG.md +97 -0
- package/dist/api/admin/apiClearAllCountersEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiClearAllCountersEndpoint.js +1 -1
- package/dist/api/admin/apiClearAllCountersEndpoint.js.map +1 -1
- package/dist/api/admin/apiDnsEventEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiDnsEventEndpoint.js +1 -1
- package/dist/api/admin/apiDnsEventEndpoint.js.map +1 -1
- package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +1 -1
- package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js.map +1 -1
- package/dist/api/admin/apiGetDecisionMachineEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiGetDecisionMachineEndpoint.js +1 -1
- package/dist/api/admin/apiGetDecisionMachineEndpoint.js.map +1 -1
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +1 -1
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js.map +1 -1
- package/dist/api/admin/apiRegisterSiteKeysEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +1 -1
- package/dist/api/admin/apiRegisterSiteKeysEndpoint.js.map +1 -1
- package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +1 -1
- package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js.map +1 -1
- package/dist/api/admin/apiRemoveDecisionMachineEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +1 -1
- package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js.map +1 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +1 -2
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js.map +1 -1
- package/dist/api/admin/apiRemoveSiteKeyEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +1 -1
- package/dist/api/admin/apiRemoveSiteKeyEndpoint.js.map +1 -1
- package/dist/api/admin/apiRemoveSiteKeysEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +1 -1
- package/dist/api/admin/apiRemoveSiteKeysEndpoint.js.map +1 -1
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +3 -1
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js.map +1 -1
- package/dist/api/admin/apiUpdateDecisionMachineEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +1 -1
- package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js.map +1 -1
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +1 -2
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js.map +1 -1
- package/dist/api/blacklistRequestInspector.d.ts.map +1 -1
- package/dist/api/blacklistRequestInspector.js +7 -3
- package/dist/api/blacklistRequestInspector.js.map +1 -1
- package/dist/api/captcha/checkSpamEmail.d.ts.map +1 -1
- package/dist/api/captcha/checkSpamEmail.js +19 -4
- package/dist/api/captcha/checkSpamEmail.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.d.ts +0 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +1 -7
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +8 -7
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +68 -28
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts +0 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +0 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js.map +1 -1
- package/dist/api/captcha/getImageCaptchaChallenge.d.ts.map +1 -1
- package/dist/api/captcha/getImageCaptchaChallenge.js +3 -0
- package/dist/api/captcha/getImageCaptchaChallenge.js.map +1 -1
- package/dist/api/captcha/getPoWCaptchaChallenge.d.ts.map +1 -1
- package/dist/api/captcha/getPoWCaptchaChallenge.js +3 -0
- package/dist/api/captcha/getPoWCaptchaChallenge.js.map +1 -1
- package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js +3 -0
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
- package/dist/api/captcha/submitPoWCaptchaSolution.d.ts +8 -0
- package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
- package/dist/api/captcha/submitPoWCaptchaSolution.js +7 -0
- package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
- package/dist/api/captcha.d.ts +2 -1
- package/dist/api/captcha.d.ts.map +1 -1
- package/dist/api/captcha.js +12 -15
- package/dist/api/captcha.js.map +1 -1
- package/dist/api/domainMiddleware.d.ts.map +1 -1
- package/dist/api/domainMiddleware.js +4 -0
- package/dist/api/domainMiddleware.js.map +1 -1
- package/dist/api/forwardVerify.d.ts +14 -0
- package/dist/api/forwardVerify.d.ts.map +1 -0
- package/dist/api/forwardVerify.js +54 -0
- package/dist/api/forwardVerify.js.map +1 -0
- package/dist/api/headerCheckMiddleware.d.ts.map +1 -1
- package/dist/api/headerCheckMiddleware.js +7 -4
- package/dist/api/headerCheckMiddleware.js.map +1 -1
- package/dist/api/ja4.d.ts +5 -0
- package/dist/api/ja4.d.ts.map +1 -0
- package/dist/api/ja4.js +203 -0
- package/dist/api/ja4.js.map +1 -0
- package/dist/api/ja4Middleware.d.ts.map +1 -1
- package/dist/api/ja4Middleware.js +9 -18
- package/dist/api/ja4Middleware.js.map +1 -1
- package/dist/api/metrics.d.ts +40 -0
- package/dist/api/metrics.d.ts.map +1 -0
- package/dist/api/metrics.js +260 -0
- package/dist/api/metrics.js.map +1 -0
- package/dist/api/public.d.ts.map +1 -1
- package/dist/api/public.js +4 -0
- package/dist/api/public.js.map +1 -1
- package/dist/api/startProviderApi.d.ts.map +1 -1
- package/dist/api/startProviderApi.js +3 -1
- package/dist/api/startProviderApi.js.map +1 -1
- package/dist/api/verify.d.ts.map +1 -1
- package/dist/api/verify.js +85 -8
- package/dist/api/verify.js.map +1 -1
- package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +1 -2
- package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +1 -2
- package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +1 -2
- package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +1 -3
- package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +1 -2
- package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +1 -2
- package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +3 -2
- package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +1 -1
- package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +1 -2
- package/dist/cjs/api/blacklistRequestInspector.cjs +7 -3
- package/dist/cjs/api/captcha/checkSpamEmail.cjs +18 -3
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +1 -7
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +8 -7
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +70 -30
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +0 -1
- package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +3 -0
- package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +3 -0
- package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +3 -0
- package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +9 -1
- package/dist/cjs/api/captcha.cjs +12 -15
- package/dist/cjs/api/domainMiddleware.cjs +4 -0
- package/dist/cjs/api/forwardVerify.cjs +54 -0
- package/dist/cjs/api/headerCheckMiddleware.cjs +7 -4
- package/dist/cjs/api/ja4.cjs +203 -0
- package/dist/cjs/api/ja4Middleware.cjs +11 -21
- package/dist/cjs/api/metrics.cjs +260 -0
- package/dist/cjs/api/public.cjs +4 -0
- package/dist/cjs/api/startProviderApi.cjs +3 -1
- package/dist/cjs/api/verify.cjs +83 -6
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/tasks/captchaManager.cjs +23 -3
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +20 -22
- package/dist/cjs/tasks/powCaptcha/powTasks.cjs +17 -23
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +15 -21
- package/dist/index.js +2 -1
- package/dist/tasks/captchaManager.d.ts.map +1 -1
- package/dist/tasks/captchaManager.js +23 -2
- package/dist/tasks/captchaManager.js.map +1 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +20 -22
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.js +17 -23
- package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js +15 -21
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
- package/dist/tests/unit/api/admin/apiClearAllCountersEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiClearAllCountersEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiDnsEventEndpoint.unit.test.js +5 -1
- package/dist/tests/unit/api/admin/apiDnsEventEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiRegisterSiteKeysEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiRegisterSiteKeysEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiRemoveDetectorKeyEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiRemoveDetectorKeyEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiUpdateDetectorKeyEndpoint.unit.test.js +1 -0
- package/dist/tests/unit/api/admin/apiUpdateDetectorKeyEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/adminRoutes.unit.test.js +1 -0
- package/dist/tests/unit/api/adminRoutes.unit.test.js.map +1 -1
- package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js +43 -0
- package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.d.ts +2 -0
- package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js +62 -0
- package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js.map +1 -0
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.unit.test.js +0 -1
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.unit.test.js +0 -1
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.d.ts +2 -0
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js +130 -0
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js.map +1 -0
- package/dist/tests/unit/api/captcha.unit.test.js +31 -1
- package/dist/tests/unit/api/captcha.unit.test.js.map +1 -1
- package/dist/tests/unit/api/forwardVerify.unit.test.d.ts +2 -0
- package/dist/tests/unit/api/forwardVerify.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/api/forwardVerify.unit.test.js +151 -0
- package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -0
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +68 -0
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
- package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js +2 -2
- package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js.map +1 -1
- package/dist/tests/unit/api/ja4.unit.test.d.ts +2 -0
- package/dist/tests/unit/api/ja4.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/api/ja4.unit.test.js +233 -0
- package/dist/tests/unit/api/ja4.unit.test.js.map +1 -0
- package/dist/tests/unit/api/ja4Middleware.unit.test.js +11 -8
- package/dist/tests/unit/api/ja4Middleware.unit.test.js.map +1 -1
- package/dist/tests/unit/api/public.unit.test.js +72 -0
- package/dist/tests/unit/api/public.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +1 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/getClientList.unit.test.js +1 -1
- package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +1 -1
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/captchaManager.unit.test.js +87 -2
- package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +1 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js +1 -1
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +4 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +1 -1
- package/package.json +23 -23
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const types = require("@prosopo/types");
|
|
4
|
+
const promClient = require("prom-client");
|
|
5
|
+
const metricsEnabled = () => process.env.PROSOPO_METRICS_ENABLED !== "false";
|
|
6
|
+
const PREFIX = "prosopo_";
|
|
7
|
+
const LATENCY_BUCKETS = [
|
|
8
|
+
5e-3,
|
|
9
|
+
0.01,
|
|
10
|
+
0.025,
|
|
11
|
+
0.05,
|
|
12
|
+
0.1,
|
|
13
|
+
0.25,
|
|
14
|
+
0.5,
|
|
15
|
+
1,
|
|
16
|
+
2.5,
|
|
17
|
+
5,
|
|
18
|
+
10
|
|
19
|
+
];
|
|
20
|
+
const SCORE_BUCKETS = [
|
|
21
|
+
0,
|
|
22
|
+
0.1,
|
|
23
|
+
0.2,
|
|
24
|
+
0.3,
|
|
25
|
+
0.4,
|
|
26
|
+
0.5,
|
|
27
|
+
0.6,
|
|
28
|
+
0.7,
|
|
29
|
+
0.8,
|
|
30
|
+
0.9,
|
|
31
|
+
1,
|
|
32
|
+
1.5,
|
|
33
|
+
2,
|
|
34
|
+
3,
|
|
35
|
+
5,
|
|
36
|
+
10
|
|
37
|
+
];
|
|
38
|
+
const KNOWN_ROUTES = /* @__PURE__ */ new Set([
|
|
39
|
+
...Object.values(types.ClientApiPaths),
|
|
40
|
+
...Object.values(types.PublicApiPaths),
|
|
41
|
+
...Object.values(types.AdminApiPaths)
|
|
42
|
+
]);
|
|
43
|
+
const normaliseRoute = (req) => {
|
|
44
|
+
const path = req.path;
|
|
45
|
+
return KNOWN_ROUTES.has(path) ? path : "other";
|
|
46
|
+
};
|
|
47
|
+
let metrics;
|
|
48
|
+
const buildMetrics = () => {
|
|
49
|
+
const registry = new promClient.Registry();
|
|
50
|
+
promClient.collectDefaultMetrics({ register: registry, prefix: PREFIX });
|
|
51
|
+
const httpRequestsTotal = new promClient.Counter({
|
|
52
|
+
name: `${PREFIX}http_requests_total`,
|
|
53
|
+
help: "Total HTTP requests handled by the provider API",
|
|
54
|
+
labelNames: ["route", "method", "status"],
|
|
55
|
+
registers: [registry]
|
|
56
|
+
});
|
|
57
|
+
const httpRequestDuration = new promClient.Histogram({
|
|
58
|
+
name: `${PREFIX}http_request_duration_seconds`,
|
|
59
|
+
help: "Provider API request duration in seconds",
|
|
60
|
+
labelNames: ["route", "method", "status"],
|
|
61
|
+
buckets: LATENCY_BUCKETS,
|
|
62
|
+
registers: [registry]
|
|
63
|
+
});
|
|
64
|
+
const captchaIssuedTotal = new promClient.Counter({
|
|
65
|
+
name: `${PREFIX}captcha_issued_total`,
|
|
66
|
+
help: "Captcha challenges issued, by type",
|
|
67
|
+
labelNames: ["type"],
|
|
68
|
+
registers: [registry]
|
|
69
|
+
});
|
|
70
|
+
const captchaIssueErrorsTotal = new promClient.Counter({
|
|
71
|
+
name: `${PREFIX}captcha_issue_errors_total`,
|
|
72
|
+
help: "Errors while issuing captcha challenges, by type",
|
|
73
|
+
labelNames: ["type"],
|
|
74
|
+
registers: [registry]
|
|
75
|
+
});
|
|
76
|
+
const captchaVerifyTotal = new promClient.Counter({
|
|
77
|
+
name: `${PREFIX}captcha_verify_total`,
|
|
78
|
+
help: "Captcha verification outcomes, by type/result/source",
|
|
79
|
+
labelNames: ["type", "result", "source"],
|
|
80
|
+
registers: [registry]
|
|
81
|
+
});
|
|
82
|
+
const frictionlessRoutedTotal = new promClient.Counter({
|
|
83
|
+
name: `${PREFIX}frictionless_routed_total`,
|
|
84
|
+
help: "Frictionless routing decisions (which captcha the user was sent to)",
|
|
85
|
+
labelNames: ["decision"],
|
|
86
|
+
registers: [registry]
|
|
87
|
+
});
|
|
88
|
+
const botScore = new promClient.Histogram({
|
|
89
|
+
name: `${PREFIX}bot_score`,
|
|
90
|
+
help: "Distribution of frictionless bot scores (0=human .. 1=bot; language-rule penalties can push it above 1)",
|
|
91
|
+
buckets: SCORE_BUCKETS,
|
|
92
|
+
registers: [registry]
|
|
93
|
+
});
|
|
94
|
+
const detectorTriggeredTotal = new promClient.Counter({
|
|
95
|
+
name: `${PREFIX}detector_triggered_total`,
|
|
96
|
+
help: "Count of times each bot detector was triggered",
|
|
97
|
+
labelNames: ["detector"],
|
|
98
|
+
registers: [registry]
|
|
99
|
+
});
|
|
100
|
+
const blockedRequestsTotal = new promClient.Counter({
|
|
101
|
+
name: `${PREFIX}blocked_requests_total`,
|
|
102
|
+
help: "Requests blocked before reaching a captcha handler, by reason",
|
|
103
|
+
labelNames: ["reason"],
|
|
104
|
+
registers: [registry]
|
|
105
|
+
});
|
|
106
|
+
const domainValidationTotal = new promClient.Counter({
|
|
107
|
+
name: `${PREFIX}domain_validation_total`,
|
|
108
|
+
help: "Domain/site-key validation outcomes",
|
|
109
|
+
labelNames: ["result"],
|
|
110
|
+
registers: [registry]
|
|
111
|
+
});
|
|
112
|
+
const spamEmailTotal = new promClient.Counter({
|
|
113
|
+
name: `${PREFIX}spam_email_total`,
|
|
114
|
+
help: "Spam email-domain check outcomes",
|
|
115
|
+
labelNames: ["result"],
|
|
116
|
+
registers: [registry]
|
|
117
|
+
});
|
|
118
|
+
const maintenanceMode = new promClient.Gauge({
|
|
119
|
+
name: `${PREFIX}maintenance_mode`,
|
|
120
|
+
help: "1 when the provider is in maintenance mode, else 0",
|
|
121
|
+
registers: [registry]
|
|
122
|
+
});
|
|
123
|
+
maintenanceMode.set(
|
|
124
|
+
process.env.MAINTENANCE_MODE?.toLowerCase() === "true" ? 1 : 0
|
|
125
|
+
);
|
|
126
|
+
const redisReady = new promClient.Gauge({
|
|
127
|
+
name: `${PREFIX}redis_ready`,
|
|
128
|
+
help: "1 when the given redis connection is ready, else 0",
|
|
129
|
+
labelNames: ["actor"],
|
|
130
|
+
registers: [registry]
|
|
131
|
+
});
|
|
132
|
+
return {
|
|
133
|
+
registry,
|
|
134
|
+
httpRequestsTotal,
|
|
135
|
+
httpRequestDuration,
|
|
136
|
+
captchaIssuedTotal,
|
|
137
|
+
captchaIssueErrorsTotal,
|
|
138
|
+
captchaVerifyTotal,
|
|
139
|
+
frictionlessRoutedTotal,
|
|
140
|
+
botScore,
|
|
141
|
+
detectorTriggeredTotal,
|
|
142
|
+
blockedRequestsTotal,
|
|
143
|
+
domainValidationTotal,
|
|
144
|
+
spamEmailTotal,
|
|
145
|
+
maintenanceMode,
|
|
146
|
+
redisReady
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
const getMetrics = () => {
|
|
150
|
+
if (!metrics) {
|
|
151
|
+
metrics = buildMetrics();
|
|
152
|
+
}
|
|
153
|
+
return metrics;
|
|
154
|
+
};
|
|
155
|
+
const recordCaptchaIssued = (type) => {
|
|
156
|
+
if (!metricsEnabled()) return;
|
|
157
|
+
getMetrics().captchaIssuedTotal.inc({ type });
|
|
158
|
+
};
|
|
159
|
+
const recordCaptchaIssueError = (type) => {
|
|
160
|
+
if (!metricsEnabled()) return;
|
|
161
|
+
getMetrics().captchaIssueErrorsTotal.inc({ type });
|
|
162
|
+
};
|
|
163
|
+
const recordCaptchaVerify = (args) => {
|
|
164
|
+
if (!metricsEnabled()) return;
|
|
165
|
+
getMetrics().captchaVerifyTotal.inc({
|
|
166
|
+
type: args.type,
|
|
167
|
+
result: args.verified ? "verified" : "failed",
|
|
168
|
+
source: args.source
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const recordFrictionlessDecision = (decision) => {
|
|
172
|
+
if (!metricsEnabled()) return;
|
|
173
|
+
getMetrics().frictionlessRoutedTotal.inc({ decision });
|
|
174
|
+
};
|
|
175
|
+
const recordBotScore = (score) => {
|
|
176
|
+
if (!metricsEnabled()) return;
|
|
177
|
+
getMetrics().botScore.observe(score);
|
|
178
|
+
};
|
|
179
|
+
const recordDetectorTriggered = (detectors) => {
|
|
180
|
+
if (!metricsEnabled()) return;
|
|
181
|
+
const m = getMetrics();
|
|
182
|
+
for (const detector of detectors) {
|
|
183
|
+
m.detectorTriggeredTotal.inc({ detector: String(detector) });
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const recordBlockedRequest = (reason) => {
|
|
187
|
+
if (!metricsEnabled()) return;
|
|
188
|
+
getMetrics().blockedRequestsTotal.inc({ reason });
|
|
189
|
+
};
|
|
190
|
+
const recordDomainValidation = (result) => {
|
|
191
|
+
if (!metricsEnabled()) return;
|
|
192
|
+
getMetrics().domainValidationTotal.inc({ result });
|
|
193
|
+
};
|
|
194
|
+
const recordSpamEmail = (result) => {
|
|
195
|
+
if (!metricsEnabled()) return;
|
|
196
|
+
getMetrics().spamEmailTotal.inc({ result });
|
|
197
|
+
};
|
|
198
|
+
const setMaintenanceModeGauge = (on) => {
|
|
199
|
+
if (!metricsEnabled()) return;
|
|
200
|
+
getMetrics().maintenanceMode.set(on ? 1 : 0);
|
|
201
|
+
};
|
|
202
|
+
const metricsMiddleware = () => {
|
|
203
|
+
return (req, res, next) => {
|
|
204
|
+
if (!metricsEnabled()) return next();
|
|
205
|
+
const start = process.hrtime.bigint();
|
|
206
|
+
res.on("finish", () => {
|
|
207
|
+
const route = normaliseRoute(req);
|
|
208
|
+
const labels = {
|
|
209
|
+
route,
|
|
210
|
+
method: req.method,
|
|
211
|
+
status: String(res.statusCode)
|
|
212
|
+
};
|
|
213
|
+
const durationSeconds = Number(process.hrtime.bigint() - start) / 1e9;
|
|
214
|
+
const m = getMetrics();
|
|
215
|
+
m.httpRequestsTotal.inc(labels);
|
|
216
|
+
m.httpRequestDuration.observe(labels, durationSeconds);
|
|
217
|
+
});
|
|
218
|
+
next();
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
const metricsHandler = (env) => {
|
|
222
|
+
return async (req, res) => {
|
|
223
|
+
const token = process.env.PROSOPO_METRICS_TOKEN;
|
|
224
|
+
if (token && req.headers.authorization !== `Bearer ${token}`) {
|
|
225
|
+
res.status(401).send("Unauthorized");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const m = getMetrics();
|
|
229
|
+
try {
|
|
230
|
+
const db = env.getDb();
|
|
231
|
+
m.redisReady.set(
|
|
232
|
+
{ actor: "general" },
|
|
233
|
+
db.getRedisConnection().isReady() ? 1 : 0
|
|
234
|
+
);
|
|
235
|
+
m.redisReady.set(
|
|
236
|
+
{ actor: "uap" },
|
|
237
|
+
db.getRedisAccessRulesConnection().isReady() ? 1 : 0
|
|
238
|
+
);
|
|
239
|
+
} catch {
|
|
240
|
+
m.redisReady.set({ actor: "general" }, 0);
|
|
241
|
+
m.redisReady.set({ actor: "uap" }, 0);
|
|
242
|
+
}
|
|
243
|
+
res.set("Content-Type", m.registry.contentType);
|
|
244
|
+
res.end(await m.registry.metrics());
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
exports.getMetrics = getMetrics;
|
|
248
|
+
exports.metricsEnabled = metricsEnabled;
|
|
249
|
+
exports.metricsHandler = metricsHandler;
|
|
250
|
+
exports.metricsMiddleware = metricsMiddleware;
|
|
251
|
+
exports.recordBlockedRequest = recordBlockedRequest;
|
|
252
|
+
exports.recordBotScore = recordBotScore;
|
|
253
|
+
exports.recordCaptchaIssueError = recordCaptchaIssueError;
|
|
254
|
+
exports.recordCaptchaIssued = recordCaptchaIssued;
|
|
255
|
+
exports.recordCaptchaVerify = recordCaptchaVerify;
|
|
256
|
+
exports.recordDetectorTriggered = recordDetectorTriggered;
|
|
257
|
+
exports.recordDomainValidation = recordDomainValidation;
|
|
258
|
+
exports.recordFrictionlessDecision = recordFrictionlessDecision;
|
|
259
|
+
exports.recordSpamEmail = recordSpamEmail;
|
|
260
|
+
exports.setMaintenanceModeGauge = setMaintenanceModeGauge;
|
package/dist/cjs/api/public.cjs
CHANGED
|
@@ -5,12 +5,16 @@ const common = require("@prosopo/common");
|
|
|
5
5
|
const types = require("@prosopo/types");
|
|
6
6
|
const util = require("@prosopo/util");
|
|
7
7
|
const express = require("express");
|
|
8
|
+
const metrics = require("./metrics.cjs");
|
|
8
9
|
function publicRouter(env) {
|
|
9
10
|
const router = express.Router();
|
|
10
11
|
router.get(types.PublicApiPaths.Healthz, (req, res) => {
|
|
11
12
|
const host = env.config.host && env.config.host.length > 0 ? env.config.host : req.hostname;
|
|
12
13
|
return res.status(200).json({ ok: true, host });
|
|
13
14
|
});
|
|
15
|
+
if (metrics.metricsEnabled()) {
|
|
16
|
+
router.get(types.PublicApiPaths.Metrics, metrics.metricsHandler(env));
|
|
17
|
+
}
|
|
14
18
|
router.get(types.PublicApiPaths.GetProviderDetails, async (req, res, next) => {
|
|
15
19
|
try {
|
|
16
20
|
const db = env.getDb();
|
|
@@ -20,6 +20,7 @@ const headerCheckMiddleware = require("./headerCheckMiddleware.cjs");
|
|
|
20
20
|
const ignoreMiddleware = require("./ignoreMiddleware.cjs");
|
|
21
21
|
const ipInfoMiddleware = require("./ipInfoMiddleware.cjs");
|
|
22
22
|
const ja4Middleware = require("./ja4Middleware.cjs");
|
|
23
|
+
const metrics = require("./metrics.cjs");
|
|
23
24
|
const _public = require("./public.cjs");
|
|
24
25
|
const robotsMiddleware = require("./robotsMiddleware.cjs");
|
|
25
26
|
const verify = require("./verify.cjs");
|
|
@@ -102,8 +103,9 @@ async function startProviderApi(env, admin = false, port) {
|
|
|
102
103
|
maxAge: 86400
|
|
103
104
|
})
|
|
104
105
|
);
|
|
105
|
-
apiApp.use(express.json({ limit: "
|
|
106
|
+
apiApp.use(express.json({ limit: "1mb" }));
|
|
106
107
|
apiApp.use(_public.publicRouter(env));
|
|
108
|
+
apiApp.use(metrics.metricsMiddleware());
|
|
107
109
|
const isTestOrDevelopmentEnv = process.env.NODE_ENV === "test" || env.config.defaultEnvironment === "development";
|
|
108
110
|
if (!isTestOrDevelopmentEnv) {
|
|
109
111
|
const configRateLimits = env.config.rateLimits;
|
package/dist/cjs/api/verify.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const api = require("@prosopo/api");
|
|
3
4
|
const apiExpressRouter = require("@prosopo/api-express-router");
|
|
4
5
|
const common = require("@prosopo/common");
|
|
5
6
|
const types = require("@prosopo/types");
|
|
@@ -7,7 +8,26 @@ const utilCrypto = require("@prosopo/util-crypto");
|
|
|
7
8
|
const express = require("express");
|
|
8
9
|
const tasks = require("../tasks/tasks.cjs");
|
|
9
10
|
const apiToggleMaintenanceModeEndpoint = require("./admin/apiToggleMaintenanceModeEndpoint.cjs");
|
|
11
|
+
const forwardVerify = require("./forwardVerify.cjs");
|
|
12
|
+
const metrics = require("./metrics.cjs");
|
|
10
13
|
const testSiteKey = require("./testSiteKey.cjs");
|
|
14
|
+
const deriveVerifySource = (body) => {
|
|
15
|
+
if (apiToggleMaintenanceModeEndpoint.getMaintenanceMode()) return "maintenance";
|
|
16
|
+
try {
|
|
17
|
+
const token = body?.token;
|
|
18
|
+
if (token) {
|
|
19
|
+
const { dapp } = types.decodeProcaptchaOutput(token);
|
|
20
|
+
if (testSiteKey.isReservedTestSiteKey(dapp)) return "test_key";
|
|
21
|
+
}
|
|
22
|
+
} catch {
|
|
23
|
+
}
|
|
24
|
+
return "real";
|
|
25
|
+
};
|
|
26
|
+
const VERIFY_PATH_TYPE = {
|
|
27
|
+
[types.ClientApiPaths.VerifyImageCaptchaSolutionDapp]: types.CaptchaType.image,
|
|
28
|
+
[types.ClientApiPaths.VerifyPowCaptchaSolution]: types.CaptchaType.pow,
|
|
29
|
+
[types.ClientApiPaths.VerifyPuzzleCaptchaSolution]: types.CaptchaType.puzzle
|
|
30
|
+
};
|
|
11
31
|
function prosopoVerifyRouter(env) {
|
|
12
32
|
const router = express.Router();
|
|
13
33
|
let userAccessRulesStorage;
|
|
@@ -20,6 +40,24 @@ function prosopoVerifyRouter(env) {
|
|
|
20
40
|
}));
|
|
21
41
|
userAccessRulesStorage = void 0;
|
|
22
42
|
}
|
|
43
|
+
router.use((req, res, next) => {
|
|
44
|
+
if (!metrics.metricsEnabled()) return next();
|
|
45
|
+
const type = VERIFY_PATH_TYPE[req.path];
|
|
46
|
+
if (!type) return next();
|
|
47
|
+
const originalJson = res.json.bind(res);
|
|
48
|
+
res.json = (body) => {
|
|
49
|
+
if (res.statusCode < 300) {
|
|
50
|
+
const verified = !!(body && typeof body === "object" && body.verified);
|
|
51
|
+
metrics.recordCaptchaVerify({
|
|
52
|
+
type,
|
|
53
|
+
verified,
|
|
54
|
+
source: deriveVerifySource(req.body)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return originalJson(body);
|
|
58
|
+
};
|
|
59
|
+
next();
|
|
60
|
+
});
|
|
23
61
|
router.post(
|
|
24
62
|
types.ClientApiPaths.VerifyImageCaptchaSolutionDapp,
|
|
25
63
|
async (req, res, next) => {
|
|
@@ -33,7 +71,6 @@ function prosopoVerifyRouter(env) {
|
|
|
33
71
|
};
|
|
34
72
|
return res.json(verificationResponse);
|
|
35
73
|
}
|
|
36
|
-
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
37
74
|
let parsed;
|
|
38
75
|
try {
|
|
39
76
|
parsed = types.VerifySolutionBody.parse(req.body);
|
|
@@ -48,7 +85,7 @@ function prosopoVerifyRouter(env) {
|
|
|
48
85
|
}
|
|
49
86
|
const { dappSignature, token, ip, maxVerifiedTime, email } = parsed;
|
|
50
87
|
try {
|
|
51
|
-
const { user, dapp, timestamp, commitmentId } = types.decodeProcaptchaOutput(token);
|
|
88
|
+
const { user, dapp, timestamp, commitmentId, providerUrl } = types.decodeProcaptchaOutput(token);
|
|
52
89
|
const testVerdict = testSiteKey.resolveTestSiteKeyVerdict(dapp, req.logger);
|
|
53
90
|
if (testVerdict !== null) {
|
|
54
91
|
const verificationResponse2 = {
|
|
@@ -57,6 +94,20 @@ function prosopoVerifyRouter(env) {
|
|
|
57
94
|
};
|
|
58
95
|
return res.json(verificationResponse2);
|
|
59
96
|
}
|
|
97
|
+
const forwarded = await forwardVerify.forwardVerifyIfNotIssuer({
|
|
98
|
+
env,
|
|
99
|
+
logger: req.logger,
|
|
100
|
+
path: types.ClientApiPaths.VerifyImageCaptchaSolutionDapp,
|
|
101
|
+
providerUrl,
|
|
102
|
+
dapp,
|
|
103
|
+
user,
|
|
104
|
+
body: parsed,
|
|
105
|
+
alreadyForwarded: req.headers[api.VERIFY_FORWARDED_HEADER] !== void 0
|
|
106
|
+
});
|
|
107
|
+
if (forwarded) {
|
|
108
|
+
return res.json(forwarded);
|
|
109
|
+
}
|
|
110
|
+
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
60
111
|
utilCrypto.validateAddress(dapp, false, 42);
|
|
61
112
|
utilCrypto.validateAddress(user, false, 42);
|
|
62
113
|
const clientRecord = await tasks$1.db.getClientRecord(dapp);
|
|
@@ -122,7 +173,6 @@ function prosopoVerifyRouter(env) {
|
|
|
122
173
|
};
|
|
123
174
|
return res.json(verificationResponse);
|
|
124
175
|
}
|
|
125
|
-
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
126
176
|
let parsed;
|
|
127
177
|
try {
|
|
128
178
|
parsed = types.ServerPowCaptchaVerifyRequestBody.parse(req.body);
|
|
@@ -137,7 +187,7 @@ function prosopoVerifyRouter(env) {
|
|
|
137
187
|
}
|
|
138
188
|
try {
|
|
139
189
|
const { token, dappSignature, ip, email } = parsed;
|
|
140
|
-
const { dapp, user, timestamp, challenge } = types.decodeProcaptchaOutput(token);
|
|
190
|
+
const { dapp, user, timestamp, challenge, providerUrl } = types.decodeProcaptchaOutput(token);
|
|
141
191
|
const testVerdict = testSiteKey.resolveTestSiteKeyVerdict(dapp, req.logger);
|
|
142
192
|
if (testVerdict !== null) {
|
|
143
193
|
const verificationResponse2 = {
|
|
@@ -146,6 +196,20 @@ function prosopoVerifyRouter(env) {
|
|
|
146
196
|
};
|
|
147
197
|
return res.json(verificationResponse2);
|
|
148
198
|
}
|
|
199
|
+
const forwarded = await forwardVerify.forwardVerifyIfNotIssuer({
|
|
200
|
+
env,
|
|
201
|
+
logger: req.logger,
|
|
202
|
+
path: types.ClientApiPaths.VerifyPowCaptchaSolution,
|
|
203
|
+
providerUrl,
|
|
204
|
+
dapp,
|
|
205
|
+
user,
|
|
206
|
+
body: parsed,
|
|
207
|
+
alreadyForwarded: req.headers[api.VERIFY_FORWARDED_HEADER] !== void 0
|
|
208
|
+
});
|
|
209
|
+
if (forwarded) {
|
|
210
|
+
return res.json(forwarded);
|
|
211
|
+
}
|
|
212
|
+
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
149
213
|
utilCrypto.validateAddress(dapp, false, 42);
|
|
150
214
|
utilCrypto.validateAddress(user, false, 42);
|
|
151
215
|
const clientRecord = await tasks$1.db.getClientRecord(dapp);
|
|
@@ -217,7 +281,6 @@ function prosopoVerifyRouter(env) {
|
|
|
217
281
|
};
|
|
218
282
|
return res.json(verificationResponse);
|
|
219
283
|
}
|
|
220
|
-
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
221
284
|
let parsed;
|
|
222
285
|
try {
|
|
223
286
|
parsed = types.ServerPuzzleCaptchaVerifyRequestBody.parse(req.body);
|
|
@@ -232,7 +295,7 @@ function prosopoVerifyRouter(env) {
|
|
|
232
295
|
}
|
|
233
296
|
try {
|
|
234
297
|
const { token, dappSignature, ip, email } = parsed;
|
|
235
|
-
const { dapp, user, timestamp, challenge } = types.decodeProcaptchaOutput(token);
|
|
298
|
+
const { dapp, user, timestamp, challenge, providerUrl } = types.decodeProcaptchaOutput(token);
|
|
236
299
|
const testVerdict = testSiteKey.resolveTestSiteKeyVerdict(dapp, req.logger);
|
|
237
300
|
if (testVerdict !== null) {
|
|
238
301
|
const verificationResponse2 = {
|
|
@@ -241,6 +304,20 @@ function prosopoVerifyRouter(env) {
|
|
|
241
304
|
};
|
|
242
305
|
return res.json(verificationResponse2);
|
|
243
306
|
}
|
|
307
|
+
const forwarded = await forwardVerify.forwardVerifyIfNotIssuer({
|
|
308
|
+
env,
|
|
309
|
+
logger: req.logger,
|
|
310
|
+
path: types.ClientApiPaths.VerifyPuzzleCaptchaSolution,
|
|
311
|
+
providerUrl,
|
|
312
|
+
dapp,
|
|
313
|
+
user,
|
|
314
|
+
body: parsed,
|
|
315
|
+
alreadyForwarded: req.headers[api.VERIFY_FORWARDED_HEADER] !== void 0
|
|
316
|
+
});
|
|
317
|
+
if (forwarded) {
|
|
318
|
+
return res.json(forwarded);
|
|
319
|
+
}
|
|
320
|
+
const tasks$1 = new tasks.Tasks(env, req.logger);
|
|
244
321
|
utilCrypto.validateAddress(dapp, false, 42);
|
|
245
322
|
utilCrypto.validateAddress(user, false, 42);
|
|
246
323
|
const clientRecord = await tasks$1.db.getClientRecord(dapp);
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ exports.getIPAddressFromBigInt = util.getIPAddressFromBigInt;
|
|
|
34
34
|
exports.shuffleArray = util.shuffleArray;
|
|
35
35
|
exports.validateIpAddress = util.validateIpAddress;
|
|
36
36
|
exports.blockMiddleware = block.blockMiddleware;
|
|
37
|
+
exports.asyncHandler = captcha.asyncHandler;
|
|
37
38
|
exports.prosopoRouter = captcha.prosopoRouter;
|
|
38
39
|
exports.prosopoVerifyRouter = verify.prosopoVerifyRouter;
|
|
39
40
|
exports.DEFAULT_JA4 = ja4Middleware.DEFAULT_JA4;
|
|
@@ -8,7 +8,6 @@ const compositeIpAddress = require("../compositeIpAddress.cjs");
|
|
|
8
8
|
const enrichDnsEvent = require("./dnsEvent/enrichDnsEvent.cjs");
|
|
9
9
|
const checkSpamEmail = require("./spam/checkSpamEmail.cjs");
|
|
10
10
|
const checkTrafficFilter = require("./spam/checkTrafficFilter.cjs");
|
|
11
|
-
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
12
11
|
const findHardBlockPolicy = (accessPolicies) => {
|
|
13
12
|
return accessPolicies.find(
|
|
14
13
|
(policy) => policy.type === userAccessPolicy.AccessPolicyType.Block && (policy.deferToVerify || !policy.captchaType)
|
|
@@ -19,7 +18,7 @@ class CaptchaManager {
|
|
|
19
18
|
this.pair = pair;
|
|
20
19
|
this.db = db;
|
|
21
20
|
this.config = config;
|
|
22
|
-
this.logger = logger$1 || logger.getLogger("info",
|
|
21
|
+
this.logger = logger$1 || logger.getLogger("info", "provider:captcha-manager");
|
|
23
22
|
this.writeQueue = writeQueue ?? null;
|
|
24
23
|
}
|
|
25
24
|
/**
|
|
@@ -149,7 +148,27 @@ class CaptchaManager {
|
|
|
149
148
|
this.writeQueue?.invalidateCachedSession(sessionId),
|
|
150
149
|
cachedHash ? this.writeQueue?.invalidateCachedSessionByHash(cachedHash) : Promise.resolve()
|
|
151
150
|
]);
|
|
152
|
-
|
|
151
|
+
let sessionRecord = await this.db.checkAndRemoveSession(sessionId);
|
|
152
|
+
let resolvedSessionId = sessionId;
|
|
153
|
+
if (!sessionRecord && this.writeQueue) {
|
|
154
|
+
const escalationSessionId = await this.writeQueue.getCachedSessionEscalation(sessionId);
|
|
155
|
+
if (escalationSessionId && escalationSessionId !== sessionId) {
|
|
156
|
+
this.logger.info(() => ({
|
|
157
|
+
msg: "Resolving origin sessionId to escalation",
|
|
158
|
+
data: {
|
|
159
|
+
account: clientSettings.account,
|
|
160
|
+
originSessionId: sessionId,
|
|
161
|
+
escalationSessionId
|
|
162
|
+
}
|
|
163
|
+
}));
|
|
164
|
+
const escalationRecord = await this.db.checkAndRemoveSession(escalationSessionId);
|
|
165
|
+
if (escalationRecord) {
|
|
166
|
+
sessionRecord = escalationRecord;
|
|
167
|
+
resolvedSessionId = escalationSessionId;
|
|
168
|
+
}
|
|
169
|
+
await this.writeQueue.invalidateCachedSessionEscalation(sessionId);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
153
172
|
if (!sessionRecord) {
|
|
154
173
|
this.logger.warn(() => ({
|
|
155
174
|
msg: "No session found",
|
|
@@ -171,6 +190,7 @@ class CaptchaManager {
|
|
|
171
190
|
type: requestedCaptchaType
|
|
172
191
|
};
|
|
173
192
|
}
|
|
193
|
+
sessionId = resolvedSessionId;
|
|
174
194
|
if (this.writeQueue) {
|
|
175
195
|
await Promise.all([
|
|
176
196
|
this.writeQueue.invalidateCachedSession(sessionId),
|
|
@@ -456,9 +456,10 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
456
456
|
return void 0;
|
|
457
457
|
}
|
|
458
458
|
async verifyImageCaptchaSolution(user, dapp, commitmentId, env, maxVerifiedTime, ip, disallowWebView, contextAwareEnabled = false, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false) {
|
|
459
|
+
const logger = this.logger.with({ commitmentId, dapp });
|
|
459
460
|
const solution = await (commitmentId ? this.getDappUserCommitmentById(commitmentId) : this.getDappUserCommitmentByAccount(user, dapp));
|
|
460
461
|
if (!solution) {
|
|
461
|
-
|
|
462
|
+
logger.debug(() => ({
|
|
462
463
|
msg: "Not verified - no solution found"
|
|
463
464
|
}));
|
|
464
465
|
return {
|
|
@@ -484,7 +485,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
484
485
|
const submittedAt = solution.submittedAtTimestamp;
|
|
485
486
|
const timeSinceCompletion = submittedAt instanceof Date ? currentTime - submittedAt.getTime() : Number.POSITIVE_INFINITY;
|
|
486
487
|
if (timeSinceCompletion > maxVerifiedTime) {
|
|
487
|
-
|
|
488
|
+
logger.debug(() => ({
|
|
488
489
|
msg: "Not verified - timed out"
|
|
489
490
|
}));
|
|
490
491
|
return {
|
|
@@ -506,7 +507,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
506
507
|
solution.ipInfo?.isValid ? solution.ipInfo.asnNumber : void 0
|
|
507
508
|
);
|
|
508
509
|
if (blockPolicy) {
|
|
509
|
-
|
|
510
|
+
logger.info(() => ({
|
|
510
511
|
msg: "User blocked by access policy in server image verification",
|
|
511
512
|
data: {
|
|
512
513
|
userAccount: solution.userAccount,
|
|
@@ -521,8 +522,8 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
521
522
|
failStatus = types.ResultReason.ACCESS_POLICY_BLOCK;
|
|
522
523
|
}
|
|
523
524
|
} catch (error) {
|
|
524
|
-
|
|
525
|
-
msg: "Failed to check user access policies in server
|
|
525
|
+
logger.warn(() => ({
|
|
526
|
+
msg: "Failed to check user access policies in server image verification",
|
|
526
527
|
error
|
|
527
528
|
}));
|
|
528
529
|
}
|
|
@@ -532,9 +533,9 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
532
533
|
const isSpam = await this.checkSpamEmail(email);
|
|
533
534
|
if (isSpam) {
|
|
534
535
|
const emailDomain = email.split("@")[1] || "unknown";
|
|
535
|
-
|
|
536
|
+
logger.info(() => ({
|
|
536
537
|
msg: "Spam email domain detected in server image verification",
|
|
537
|
-
data: {
|
|
538
|
+
data: { emailDomain }
|
|
538
539
|
}));
|
|
539
540
|
commitmentUpdates.result = {
|
|
540
541
|
status: types.CaptchaStatus.disapproved,
|
|
@@ -543,7 +544,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
543
544
|
failStatus = types.ResultReason.SPAM_EMAIL_DOMAIN;
|
|
544
545
|
}
|
|
545
546
|
} catch (error) {
|
|
546
|
-
|
|
547
|
+
logger.warn(() => ({
|
|
547
548
|
msg: "Failed to check spam email domain in server image verification",
|
|
548
549
|
error
|
|
549
550
|
}));
|
|
@@ -552,9 +553,9 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
552
553
|
if (!failStatus && spamFilter?.enabled && spamFilter.emailRules?.enabled && email) {
|
|
553
554
|
const result = evaluateEmailSpamRules.evaluateEmailSpamRules(email, spamFilter.emailRules);
|
|
554
555
|
if (result.isSpam) {
|
|
555
|
-
|
|
556
|
+
logger.info(() => ({
|
|
556
557
|
msg: "Spam filter rejected email in image verification",
|
|
557
|
-
data: {
|
|
558
|
+
data: { reason: result.reason }
|
|
558
559
|
}));
|
|
559
560
|
commitmentUpdates.result = {
|
|
560
561
|
status: types.CaptchaStatus.disapproved,
|
|
@@ -578,11 +579,9 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
578
579
|
enrichedDnsEvent
|
|
579
580
|
);
|
|
580
581
|
if (check.isBlocked) {
|
|
581
|
-
|
|
582
|
+
logger.info(() => ({
|
|
582
583
|
msg: "Traffic filter rejected request",
|
|
583
584
|
data: {
|
|
584
|
-
commitmentId,
|
|
585
|
-
dapp,
|
|
586
585
|
ip,
|
|
587
586
|
reason: check.reason,
|
|
588
587
|
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
@@ -611,13 +610,13 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
611
610
|
const ipValidation = await util.deepValidateIpAddress(
|
|
612
611
|
ip,
|
|
613
612
|
solutionIpAddress,
|
|
614
|
-
|
|
613
|
+
logger,
|
|
615
614
|
env.ipInfoService,
|
|
616
615
|
ipValidationRules,
|
|
617
616
|
enrichedDnsEvent?.peerIp
|
|
618
617
|
);
|
|
619
618
|
if (!ipValidation.isValid) {
|
|
620
|
-
|
|
619
|
+
logger.error(() => ({
|
|
621
620
|
msg: "IP validation failed for image captcha",
|
|
622
621
|
data: {
|
|
623
622
|
ip,
|
|
@@ -658,7 +657,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
658
657
|
};
|
|
659
658
|
}
|
|
660
659
|
score = frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
661
|
-
|
|
660
|
+
logger.info(() => ({
|
|
662
661
|
data: {
|
|
663
662
|
scoreComponents: sessionRecord?.scoreComponents,
|
|
664
663
|
score,
|
|
@@ -667,7 +666,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
667
666
|
}
|
|
668
667
|
}));
|
|
669
668
|
if (!failStatus && disallowWebView === true && (sessionRecord.webView === true || (sessionRecord.scoreComponents.webView || 0) > 0)) {
|
|
670
|
-
|
|
669
|
+
logger.info(() => ({
|
|
671
670
|
msg: "Disallowing webview access - user not verified"
|
|
672
671
|
}));
|
|
673
672
|
commitmentUpdates.result = {
|
|
@@ -679,7 +678,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
679
678
|
failureStatus = types.ResultReason.DISALLOWED_WEBVIEW;
|
|
680
679
|
}
|
|
681
680
|
if (contextAwareEnabled && sessionRecord.reason === types.FrictionlessReason.CONTEXT_AWARE_VALIDATION_FAILED) {
|
|
682
|
-
|
|
681
|
+
logger.info(() => ({
|
|
683
682
|
msg: "Context aware validation failed"
|
|
684
683
|
}));
|
|
685
684
|
}
|
|
@@ -708,14 +707,13 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
708
707
|
try {
|
|
709
708
|
const decision = await this.decisionMachineRunner.decide(
|
|
710
709
|
decisionInput,
|
|
711
|
-
|
|
710
|
+
logger
|
|
712
711
|
);
|
|
713
712
|
if (decision.decision === types.DecisionMachineDecision.Deny) {
|
|
714
713
|
const dmReason = decision.reason || types.ResultReason.CAPTCHA_DECISION_MACHINE_DENIED;
|
|
715
|
-
|
|
714
|
+
logger.info(() => ({
|
|
716
715
|
msg: "Decision machine denied user verification",
|
|
717
716
|
data: {
|
|
718
|
-
commitmentId,
|
|
719
717
|
reason: decision.reason
|
|
720
718
|
}
|
|
721
719
|
}));
|
|
@@ -727,7 +725,7 @@ class ImgCaptchaManager extends captchaManager.CaptchaManager {
|
|
|
727
725
|
failureStatus = dmReason;
|
|
728
726
|
}
|
|
729
727
|
} catch (error) {
|
|
730
|
-
|
|
728
|
+
logger.error(() => ({
|
|
731
729
|
msg: "Failed to process decision machine",
|
|
732
730
|
err: error
|
|
733
731
|
}));
|