@prosopo/provider 3.13.0 → 3.13.7
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 +103 -0
- package/.turbo/turbo-build.log +103 -0
- package/CHANGELOG.md +120 -0
- package/dist/api/captcha/contextAwareValidation.js +20 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +83 -55
- package/dist/cjs/api/captcha/contextAwareValidation.cjs +20 -0
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +82 -54
- package/dist/cjs/tasks/client/clientTasks.cjs +72 -8
- package/dist/cjs/tasks/detection/decodePayload.cjs +731 -385
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +9 -4
- package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +4 -1
- package/dist/tasks/client/clientTasks.js +73 -9
- package/dist/tasks/detection/decodePayload.js +731 -385
- package/dist/tasks/detection/getBotScore.js +2 -2
- package/dist/tasks/frictionless/frictionlessTasks.js +9 -4
- package/dist/tasks/frictionless/frictionlessTasksUtils.js +4 -1
- package/package.json +20 -20
|
@@ -249,6 +249,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
249
249
|
let webView;
|
|
250
250
|
let iFrame;
|
|
251
251
|
let decryptedHeadHash = "";
|
|
252
|
+
let decryptionFailed = false;
|
|
252
253
|
for (const [keyIndex, key] of decryptKeys.entries()) {
|
|
253
254
|
try {
|
|
254
255
|
this.logger.info(() => ({
|
|
@@ -296,6 +297,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
296
297
|
timestamp = 0;
|
|
297
298
|
providerSelectEntropy = DEFAULT_ENTROPY + 1;
|
|
298
299
|
decryptedHeadHash = "";
|
|
300
|
+
decryptionFailed = true;
|
|
299
301
|
}
|
|
300
302
|
}
|
|
301
303
|
}
|
|
@@ -311,6 +313,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
311
313
|
timestamp = 0;
|
|
312
314
|
providerSelectEntropy = DEFAULT_ENTROPY - undefinedCount;
|
|
313
315
|
decryptedHeadHash = "";
|
|
316
|
+
decryptionFailed = true;
|
|
314
317
|
}
|
|
315
318
|
this.logger.info(() => ({
|
|
316
319
|
msg: "decryptPayload result",
|
|
@@ -322,7 +325,8 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
322
325
|
userAgent,
|
|
323
326
|
webView,
|
|
324
327
|
iFrame,
|
|
325
|
-
decryptedHeadHash
|
|
328
|
+
decryptedHeadHash,
|
|
329
|
+
decryptionFailed
|
|
326
330
|
}
|
|
327
331
|
}));
|
|
328
332
|
return {
|
|
@@ -333,11 +337,12 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
333
337
|
userAgent,
|
|
334
338
|
webView: webView || false,
|
|
335
339
|
iFrame: iFrame || false,
|
|
336
|
-
decryptedHeadHash
|
|
340
|
+
decryptedHeadHash,
|
|
341
|
+
decryptionFailed
|
|
337
342
|
};
|
|
338
343
|
}
|
|
339
|
-
async
|
|
340
|
-
return this.db.
|
|
344
|
+
async getClientContextEntropy(siteKey, contextType) {
|
|
345
|
+
return this.db.getClientContextEntropy(siteKey, contextType);
|
|
341
346
|
}
|
|
342
347
|
}
|
|
343
348
|
exports.DEFAULT_ENTROPY = DEFAULT_ENTROPY;
|
|
@@ -8,7 +8,10 @@ const computeFrictionlessScore = (scoreComponents) => {
|
|
|
8
8
|
).toFixed(2)
|
|
9
9
|
);
|
|
10
10
|
};
|
|
11
|
-
const timestampDecayFunction = (timestamp) => {
|
|
11
|
+
const timestampDecayFunction = (timestamp, decryptionFailed) => {
|
|
12
|
+
if (decryptionFailed) {
|
|
13
|
+
return 6;
|
|
14
|
+
}
|
|
12
15
|
const max = (/* @__PURE__ */ new Date()).getTime();
|
|
13
16
|
if (max - timestamp > 36e5) {
|
|
14
17
|
return 12;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createPrivateKey } from "node:crypto";
|
|
2
2
|
import { ProsopoApiError } from "@prosopo/common";
|
|
3
3
|
import { CaptchaDatabase, ClientDatabase } from "@prosopo/database";
|
|
4
|
-
import { ScheduledTaskNames, ScheduledTaskStatus } from "@prosopo/types";
|
|
4
|
+
import { ScheduledTaskNames, ScheduledTaskStatus, Tier } from "@prosopo/types";
|
|
5
5
|
import { majorityAverage, parseUrl } from "@prosopo/util";
|
|
6
6
|
import { validateSiteKey } from "../../api/validateAddress.js";
|
|
7
|
+
const SAMPLE_SIZE = 100;
|
|
7
8
|
const isValidPrivateKey = (privateKeyString) => {
|
|
8
9
|
const privateKey = Buffer.from(privateKeyString, "base64").toString("ascii");
|
|
9
10
|
try {
|
|
@@ -161,7 +162,13 @@ class ClientTaskManager {
|
|
|
161
162
|
this.logger
|
|
162
163
|
);
|
|
163
164
|
const tenMinuteWindow = 10 * 60 * 1e3;
|
|
164
|
-
const updatedAtTimestamp =
|
|
165
|
+
const updatedAtTimestamp = (() => {
|
|
166
|
+
const raw = lastTask?.updated;
|
|
167
|
+
if (!raw) return 0;
|
|
168
|
+
const ts = raw instanceof Date ? raw.getTime() : Date.parse(String(raw));
|
|
169
|
+
if (Number.isNaN(ts)) return 0;
|
|
170
|
+
return Math.max(ts - tenMinuteWindow, 0);
|
|
171
|
+
})();
|
|
165
172
|
this.logger.info(() => ({
|
|
166
173
|
msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`
|
|
167
174
|
}));
|
|
@@ -199,14 +206,71 @@ class ClientTaskManager {
|
|
|
199
206
|
* @returns Promise<void>
|
|
200
207
|
*/
|
|
201
208
|
async calculateClientEntropy() {
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(
|
|
210
|
+
ScheduledTaskNames.SetClientEntropy,
|
|
211
|
+
ScheduledTaskStatus.Running
|
|
212
|
+
);
|
|
213
|
+
try {
|
|
214
|
+
let clients = await this.providerDB.getAllClientRecords();
|
|
215
|
+
clients = clients.filter((client) => client.tier !== Tier.Free);
|
|
216
|
+
this.logger.info(() => ({
|
|
217
|
+
msg: `Calculating entropies for ${clients.length} clients`
|
|
218
|
+
}));
|
|
219
|
+
for (const client of clients) {
|
|
220
|
+
if (client.settings?.contextAware?.enabled) {
|
|
221
|
+
const contextTypes = Object.keys(
|
|
222
|
+
client.settings.contextAware.contexts ?? {}
|
|
223
|
+
);
|
|
224
|
+
for (const contextType of contextTypes) {
|
|
225
|
+
const contextSamples = await this.providerDB.sampleContextEntropy(
|
|
226
|
+
SAMPLE_SIZE,
|
|
227
|
+
client.account,
|
|
228
|
+
contextType
|
|
229
|
+
);
|
|
230
|
+
if (contextSamples.length < SAMPLE_SIZE) {
|
|
231
|
+
this.logger.info(() => ({
|
|
232
|
+
msg: `Skipping ${contextType} entropy calculation for client ${client.account} due to insufficient samples (${contextSamples.length}/${SAMPLE_SIZE})`
|
|
233
|
+
}));
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const contextAvgEntropy = majorityAverage(contextSamples);
|
|
237
|
+
this.logger.info(() => ({
|
|
238
|
+
msg: `Calculated ${contextType} entropy for client ${client.account}: ${contextAvgEntropy}`
|
|
239
|
+
}));
|
|
240
|
+
await this.providerDB.setClientContextEntropy(
|
|
241
|
+
client.account,
|
|
242
|
+
contextType,
|
|
243
|
+
contextAvgEntropy
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
249
|
+
taskID,
|
|
250
|
+
ScheduledTaskStatus.Completed,
|
|
251
|
+
{
|
|
252
|
+
data: {
|
|
253
|
+
clientRecords: clients.length
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
const calculateClientEntropiesError = new ProsopoApiError(
|
|
259
|
+
"DATABASE.UNKNOWN",
|
|
260
|
+
{
|
|
261
|
+
context: { error: e },
|
|
262
|
+
logger: this.logger
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
this.logger.error(() => ({
|
|
266
|
+
err: calculateClientEntropiesError,
|
|
267
|
+
msg: "Error calculating client entropy"
|
|
268
|
+
}));
|
|
269
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
270
|
+
taskID,
|
|
271
|
+
ScheduledTaskStatus.Failed,
|
|
272
|
+
{ error: String(e) }
|
|
207
273
|
);
|
|
208
|
-
const avgEntropy = majorityAverage(sampleEntropies);
|
|
209
|
-
await this.providerDB.setClientEntropy(client.account, avgEntropy);
|
|
210
274
|
}
|
|
211
275
|
}
|
|
212
276
|
async registerSiteKey(siteKey, tier, settings) {
|