@prosopo/procaptcha-frictionless 2.12.10 → 2.12.11
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 +3 -3
- package/.turbo/turbo-build$colon$tsc.log +25 -25
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +25 -0
- package/dist/cjs/customDetectBot.cjs +11 -7
- package/dist/customDetectBot.d.ts.map +1 -1
- package/dist/customDetectBot.js +11 -7
- package/dist/customDetectBot.js.map +1 -1
- package/package.json +9 -9
- package/src/customDetectBot.ts +38 -23
- package/src/tests/customDetectBotSimd.test.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-frictionless@2.12.
|
|
2
|
+
> @prosopo/procaptcha-frictionless@2.12.11 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -61,6 +61,6 @@ rendering chunks...
|
|
|
61
61
|
[2mdist/cjs/[22m[36mindex.cjs [39m[1m[2m0.24 kB[22m[1m[22m
|
|
62
62
|
[2mdist/cjs/[22m[36msessionInvalidatedRecovery.cjs [39m[1m[2m0.85 kB[22m[1m[22m
|
|
63
63
|
[2mdist/cjs/[22m[36mdetectorLoader.cjs [39m[1m[2m1.37 kB[22m[1m[22m
|
|
64
|
-
[2mdist/cjs/[22m[36mcustomDetectBot.cjs [39m[1m[2m4.
|
|
64
|
+
[2mdist/cjs/[22m[36mcustomDetectBot.cjs [39m[1m[2m4.26 kB[22m[1m[22m
|
|
65
65
|
[2mdist/cjs/[22m[36mProcaptchaFrictionless.cjs [39m[1m[2m9.11 kB[22m[1m[22m
|
|
66
|
-
[32m✓ built in
|
|
66
|
+
[32m✓ built in 86ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-frictionless@2.12.
|
|
2
|
+
> @prosopo/procaptcha-frictionless@2.12.11 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
10:35:14 AM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../locale/tsconfig.json
|
|
8
8
|
* ../util/tsconfig.json
|
|
@@ -26,49 +26,49 @@
|
|
|
26
26
|
* ../procaptcha-react/tsconfig.json
|
|
27
27
|
* tsconfig.json
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
10:35:14 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
10:35:14 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
10:35:14 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
10:35:14 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
10:35:14 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/provider/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
10:35:14 AM - Project '../detector/tsconfig.json' is up to date because newest input '../detector/src/index.js' is older than output '../detector/tsconfig.tsbuildinfo'
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
10:35:14 AM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
10:35:14 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
10:35:14 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/error.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
10:35:14 AM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/browser.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
10:35:14 AM - Project '../fingerprint/tsconfig.json' is up to date because newest input '../fingerprint/src/index.ts' is older than output '../fingerprint/tsconfig.tsbuildinfo'
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
10:35:14 AM - Project '../load-balancer/tsconfig.json' is up to date because newest input '../load-balancer/src/balancer.ts' is older than output '../load-balancer/tsconfig.tsbuildinfo'
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
10:35:15 AM - Project '../widget-skeleton/tsconfig.json' is up to date because newest input '../widget-skeleton/src/constants.ts' is older than output '../widget-skeleton/tsconfig.tsbuildinfo'
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
10:35:15 AM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/index.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
10:35:15 AM - Project '../account/tsconfig.json' is up to date because newest input '../account/src/workers/cryptoWorker.ts' is older than output '../account/tsconfig.tsbuildinfo'
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
10:35:15 AM - Project '../procaptcha-common/tsconfig.json' is up to date because newest input '../procaptcha-common/src/tests/defaultEvents.test.ts' is older than output '../procaptcha-common/tsconfig.tsbuildinfo'
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
10:35:15 AM - Project '../procaptcha-pow/tsconfig.json' is up to date because newest input '../procaptcha-pow/src/index.ts' is older than output '../procaptcha-pow/tsconfig.tsbuildinfo'
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
10:35:15 AM - Project '../procaptcha-puzzle/tsconfig.json' is up to date because newest input '../procaptcha-puzzle/src/index.ts' is older than output '../procaptcha-puzzle/tsconfig.tsbuildinfo'
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
10:35:15 AM - Project '../datasets/tsconfig.json' is up to date because newest input '../datasets/src/index.ts' is older than output '../datasets/tsconfig.tsbuildinfo'
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
10:35:15 AM - Project '../procaptcha/tsconfig.json' is up to date because newest input '../procaptcha/src/index.ts' is older than output '../procaptcha/tsconfig.tsbuildinfo'
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
10:35:15 AM - Project '../procaptcha-react/tsconfig.json' is up to date because newest input '../procaptcha-react/src/index.ts' is older than output '../procaptcha-react/tsconfig.tsbuildinfo'
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
10:35:15 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
10:35:15 AM - Building project '/home/runner/work/captcha/captcha/packages/procaptcha-frictionless/tsconfig.json'...
|
|
74
74
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-frictionless@2.12.
|
|
2
|
+
> @prosopo/procaptcha-frictionless@2.12.11 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/procaptcha-frictionless@2.12.
|
|
6
|
+
> @prosopo/procaptcha-frictionless@2.12.11 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -64,6 +64,6 @@ rendering chunks...
|
|
|
64
64
|
[2mdist/[22m[36mindex.js [39m[1m[2m0.11 kB[22m[1m[22m
|
|
65
65
|
[2mdist/[22m[36mdetectorLoader.js [39m[1m[2m0.11 kB[22m[1m[22m
|
|
66
66
|
[2mdist/[22m[36msessionInvalidatedRecovery.js [39m[1m[2m0.71 kB[22m[1m[22m
|
|
67
|
-
[2mdist/[22m[36mcustomDetectBot.js [39m[1m[
|
|
67
|
+
[2mdist/[22m[36mcustomDetectBot.js [39m[1m[2m4.08 kB[22m[1m[22m
|
|
68
68
|
[2mdist/[22m[36mProcaptchaFrictionless.js [39m[1m[2m7.67 kB[22m[1m[22m
|
|
69
|
-
[32m✓ built in
|
|
69
|
+
[32m✓ built in 146ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @prosopo/procaptcha-frictionless
|
|
2
2
|
|
|
3
|
+
## 2.12.11
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- 85e8857: Record both the top-frame URL and the widget's own iframe URL on frictionless sessions.
|
|
7
|
+
|
|
8
|
+
Previously the client only sent one field (`currentUrl`), which for embedded widgets resolved to the top-frame URL — so we lost visibility into which iframe endpoint the session was actually loaded through. Now the client sends both:
|
|
9
|
+
|
|
10
|
+
- `currentUrl`: the top-frame URL (same resolution rules as before — same-origin iframes read `window.top.location.href` directly; cross-origin iframes fall back to `document.referrer`).
|
|
11
|
+
- `iframeUrl`: the widget's own frame URL when embedded. Undefined when the widget IS the top frame (nothing to distinguish).
|
|
12
|
+
|
|
13
|
+
Both fields are sanitised client- and server-side (origin + path only; query string, fragment and any embedded credentials stripped). The provider persists both on the `Session` record and re-uses them on post-PoW escalation sessions. Only `currentUrl` is gated in the frictionless decision machine (unchanged — missing `currentUrl` still forces an image captcha); `iframeUrl` is recorded for analytics.
|
|
14
|
+
|
|
15
|
+
Both fields are also surfaced to the decision machines as raw signals: `RoutingMachineRawSignals` gains an optional `iframeUrl` populated from the freshly decrypted frictionless payload on the `route` phase, from the persisted Session record on the `postPow` phase, and from the cached Session in the dedup replay path — matching how `currentUrl` is already threaded through.
|
|
16
|
+
|
|
17
|
+
Additionally, sessions carry a new computed boolean `isProtect`, set at session-creation time when the widget iframe was served from `protect.<tenant>` and embedded in a page on the same tenant (subdomain-of matching, dot-boundary safe — see `isProtectDeployment` in `@prosopo/util`). Persisted only when true (same pattern as `isEscalation`) and backed by a sparse `{isProtect, createdAt}` index so analytics can cheaply retrieve Protect sessions without re-parsing URLs. Post-PoW escalation sessions inherit the flag from the origin session.
|
|
18
|
+
- Updated dependencies [85e8857]
|
|
19
|
+
- @prosopo/api@3.5.15
|
|
20
|
+
- @prosopo/types@4.9.8
|
|
21
|
+
- @prosopo/procaptcha-pow@2.10.15
|
|
22
|
+
- @prosopo/procaptcha-puzzle@2.10.30
|
|
23
|
+
- @prosopo/common@3.1.44
|
|
24
|
+
- @prosopo/detector@3.5.9
|
|
25
|
+
- @prosopo/procaptcha-common@2.11.9
|
|
26
|
+
- @prosopo/procaptcha-react@2.9.88
|
|
27
|
+
|
|
3
28
|
## 2.12.10
|
|
4
29
|
### Patch Changes
|
|
5
30
|
|
|
@@ -13,27 +13,29 @@ const sanitiseHref = (href) => {
|
|
|
13
13
|
return void 0;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
const
|
|
16
|
+
const getCurrentPageUrls = () => {
|
|
17
17
|
if (typeof window === "undefined" || !window.location) {
|
|
18
|
-
return void 0;
|
|
18
|
+
return { currentUrl: void 0, iframeUrl: void 0 };
|
|
19
19
|
}
|
|
20
20
|
const local = (() => {
|
|
21
21
|
const { origin, pathname } = window.location;
|
|
22
22
|
if (!origin || origin === "null") return void 0;
|
|
23
23
|
return `${origin}${pathname || ""}`;
|
|
24
24
|
})();
|
|
25
|
-
if (window === window.top)
|
|
25
|
+
if (window === window.top) {
|
|
26
|
+
return { currentUrl: local, iframeUrl: void 0 };
|
|
27
|
+
}
|
|
26
28
|
try {
|
|
27
29
|
const topHref = window.top?.location?.href;
|
|
28
30
|
const sanitised = topHref ? sanitiseHref(topHref) : void 0;
|
|
29
|
-
if (sanitised) return sanitised;
|
|
31
|
+
if (sanitised) return { currentUrl: sanitised, iframeUrl: local };
|
|
30
32
|
} catch {
|
|
31
33
|
}
|
|
32
34
|
if (typeof document !== "undefined" && document.referrer) {
|
|
33
35
|
const fromReferrer = sanitiseHref(document.referrer);
|
|
34
|
-
if (fromReferrer) return fromReferrer;
|
|
36
|
+
if (fromReferrer) return { currentUrl: fromReferrer, iframeUrl: local };
|
|
35
37
|
}
|
|
36
|
-
return local;
|
|
38
|
+
return { currentUrl: local, iframeUrl: local };
|
|
37
39
|
};
|
|
38
40
|
const withTimeout = async (promise, ms) => {
|
|
39
41
|
let timeoutId;
|
|
@@ -81,6 +83,7 @@ const customDetectBot = async (config, container, restartFn, retryContext) => {
|
|
|
81
83
|
provider.provider.url,
|
|
82
84
|
config.account.address
|
|
83
85
|
);
|
|
86
|
+
const { currentUrl, iframeUrl } = getCurrentPageUrls();
|
|
84
87
|
const captchaPromise = providerApi.getFrictionlessCaptcha(
|
|
85
88
|
detectionResult.token,
|
|
86
89
|
detectionResult.encryptHeadHash,
|
|
@@ -88,7 +91,8 @@ const customDetectBot = async (config, container, restartFn, retryContext) => {
|
|
|
88
91
|
userAccount.account.address,
|
|
89
92
|
config.mode,
|
|
90
93
|
void 0,
|
|
91
|
-
|
|
94
|
+
currentUrl,
|
|
95
|
+
iframeUrl
|
|
92
96
|
);
|
|
93
97
|
if (detectionResult.getSimdReadings) {
|
|
94
98
|
void detectionResult.getSimdReadings(6e4).catch(() => void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customDetectBot.d.ts","sourceRoot":"","sources":["../src/customDetectBot.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACX,oBAAoB,EAGpB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"customDetectBot.d.ts","sourceRoot":"","sources":["../src/customDetectBot.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACX,oBAAoB,EAGpB,MAAM,gBAAgB,CAAC;AA2ExB,eAAO,MAAM,WAAW,GAAU,CAAC,WACzB,OAAO,CAAC,CAAC,CAAC,MACf,MAAM,KACR,OAAO,CAAC,CAAC,CAoBX,CAAC;AAEF,QAAA,MAAM,eAAe,EAAE,oBA0GtB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
package/dist/customDetectBot.js
CHANGED
|
@@ -11,27 +11,29 @@ const sanitiseHref = (href) => {
|
|
|
11
11
|
return void 0;
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
|
-
const
|
|
14
|
+
const getCurrentPageUrls = () => {
|
|
15
15
|
if (typeof window === "undefined" || !window.location) {
|
|
16
|
-
return void 0;
|
|
16
|
+
return { currentUrl: void 0, iframeUrl: void 0 };
|
|
17
17
|
}
|
|
18
18
|
const local = (() => {
|
|
19
19
|
const { origin, pathname } = window.location;
|
|
20
20
|
if (!origin || origin === "null") return void 0;
|
|
21
21
|
return `${origin}${pathname || ""}`;
|
|
22
22
|
})();
|
|
23
|
-
if (window === window.top)
|
|
23
|
+
if (window === window.top) {
|
|
24
|
+
return { currentUrl: local, iframeUrl: void 0 };
|
|
25
|
+
}
|
|
24
26
|
try {
|
|
25
27
|
const topHref = window.top?.location?.href;
|
|
26
28
|
const sanitised = topHref ? sanitiseHref(topHref) : void 0;
|
|
27
|
-
if (sanitised) return sanitised;
|
|
29
|
+
if (sanitised) return { currentUrl: sanitised, iframeUrl: local };
|
|
28
30
|
} catch {
|
|
29
31
|
}
|
|
30
32
|
if (typeof document !== "undefined" && document.referrer) {
|
|
31
33
|
const fromReferrer = sanitiseHref(document.referrer);
|
|
32
|
-
if (fromReferrer) return fromReferrer;
|
|
34
|
+
if (fromReferrer) return { currentUrl: fromReferrer, iframeUrl: local };
|
|
33
35
|
}
|
|
34
|
-
return local;
|
|
36
|
+
return { currentUrl: local, iframeUrl: local };
|
|
35
37
|
};
|
|
36
38
|
const withTimeout = async (promise, ms) => {
|
|
37
39
|
let timeoutId;
|
|
@@ -79,6 +81,7 @@ const customDetectBot = async (config, container, restartFn, retryContext) => {
|
|
|
79
81
|
provider.provider.url,
|
|
80
82
|
config.account.address
|
|
81
83
|
);
|
|
84
|
+
const { currentUrl, iframeUrl } = getCurrentPageUrls();
|
|
82
85
|
const captchaPromise = providerApi.getFrictionlessCaptcha(
|
|
83
86
|
detectionResult.token,
|
|
84
87
|
detectionResult.encryptHeadHash,
|
|
@@ -86,7 +89,8 @@ const customDetectBot = async (config, container, restartFn, retryContext) => {
|
|
|
86
89
|
userAccount.account.address,
|
|
87
90
|
config.mode,
|
|
88
91
|
void 0,
|
|
89
|
-
|
|
92
|
+
currentUrl,
|
|
93
|
+
iframeUrl
|
|
90
94
|
);
|
|
91
95
|
if (detectionResult.getSimdReadings) {
|
|
92
96
|
void detectionResult.getSimdReadings(6e4).catch(() => void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customDetectBot.js","sourceRoot":"","sources":["../src/customDetectBot.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACN,eAAe,EACf,iCAAiC,EACjC,UAAU,GACV,MAAM,4BAA4B,CAAC;AAOpC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"customDetectBot.js","sourceRoot":"","sources":["../src/customDetectBot.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/procaptcha-frictionless",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.11",
|
|
4
4
|
"author": "PROSOPO LIMITED <info@prosopo.io>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,15 +30,15 @@
|
|
|
30
30
|
},
|
|
31
31
|
"browserslist": ["> 0.5%, last 2 versions, not dead"],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@prosopo/api": "3.5.
|
|
34
|
-
"@prosopo/common": "3.1.
|
|
35
|
-
"@prosopo/detector": "3.5.
|
|
33
|
+
"@prosopo/api": "3.5.15",
|
|
34
|
+
"@prosopo/common": "3.1.44",
|
|
35
|
+
"@prosopo/detector": "3.5.9",
|
|
36
36
|
"@prosopo/locale": "3.2.6",
|
|
37
|
-
"@prosopo/procaptcha-common": "2.11.
|
|
38
|
-
"@prosopo/procaptcha-pow": "2.10.
|
|
39
|
-
"@prosopo/procaptcha-puzzle": "2.10.
|
|
40
|
-
"@prosopo/procaptcha-react": "2.9.
|
|
41
|
-
"@prosopo/types": "4.9.
|
|
37
|
+
"@prosopo/procaptcha-common": "2.11.9",
|
|
38
|
+
"@prosopo/procaptcha-pow": "2.10.15",
|
|
39
|
+
"@prosopo/procaptcha-puzzle": "2.10.30",
|
|
40
|
+
"@prosopo/procaptcha-react": "2.9.88",
|
|
41
|
+
"@prosopo/types": "4.9.8",
|
|
42
42
|
"@prosopo/widget-skeleton": "2.8.4",
|
|
43
43
|
"dotenv": "16.4.5",
|
|
44
44
|
"react": "18.3.1"
|
package/src/customDetectBot.ts
CHANGED
|
@@ -27,22 +27,25 @@ import type {
|
|
|
27
27
|
import type { BotDetectionFunctionResult } from "@prosopo/types";
|
|
28
28
|
import { DetectorLoader } from "./detectorLoader.js";
|
|
29
29
|
|
|
30
|
-
// The page the widget is rendered on, reduced to origin + path.
|
|
31
|
-
// built from `origin` + `pathname` (never `href`) so the query
|
|
32
|
-
// fragment, and any embedded `user:pass@` credentials never leave the
|
|
33
|
-
// — sites routinely carry tokens / session ids / reset codes in those
|
|
34
|
-
//
|
|
35
|
-
// origins; the provider then treats the session as having no page URL and
|
|
36
|
-
// forces an image captcha.
|
|
30
|
+
// The page(s) the widget is rendered on, reduced to origin + path.
|
|
31
|
+
// Deliberately built from `origin` + `pathname` (never `href`) so the query
|
|
32
|
+
// string, fragment, and any embedded `user:pass@` credentials never leave the
|
|
33
|
+
// browser — sites routinely carry tokens / session ids / reset codes in those
|
|
34
|
+
// parts.
|
|
37
35
|
//
|
|
38
|
-
//
|
|
39
|
-
// `
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
36
|
+
// Returns two fields:
|
|
37
|
+
// - `currentUrl`: the top-frame URL as best we can determine it. Same-origin
|
|
38
|
+
// iframes read it directly; cross-origin iframes fall back to
|
|
39
|
+
// `document.referrer`, which the browser fills with the embedding page URL
|
|
40
|
+
// subject to Referrer-Policy. When neither is available the field falls
|
|
41
|
+
// back to the local (iframe) URL so the provider still sees a value.
|
|
42
|
+
// - `iframeUrl`: the widget's own frame URL when we're embedded. Undefined
|
|
43
|
+
// when the widget IS the top frame — nothing to distinguish. Emitted so
|
|
44
|
+
// downstream analytics can separate "Protect's site-wide iframe endpoint"
|
|
45
|
+
// from "the page the user was actually on".
|
|
46
|
+
//
|
|
47
|
+
// Both fields are undefined in non-browser contexts (SSR / tests) or for
|
|
48
|
+
// opaque origins.
|
|
46
49
|
const sanitiseHref = (href: string): string | undefined => {
|
|
47
50
|
try {
|
|
48
51
|
const u = new URL(href);
|
|
@@ -53,9 +56,14 @@ const sanitiseHref = (href: string): string | undefined => {
|
|
|
53
56
|
}
|
|
54
57
|
};
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
type PageUrls = {
|
|
60
|
+
currentUrl: string | undefined;
|
|
61
|
+
iframeUrl: string | undefined;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const getCurrentPageUrls = (): PageUrls => {
|
|
57
65
|
if (typeof window === "undefined" || !window.location) {
|
|
58
|
-
return undefined;
|
|
66
|
+
return { currentUrl: undefined, iframeUrl: undefined };
|
|
59
67
|
}
|
|
60
68
|
const local = (() => {
|
|
61
69
|
const { origin, pathname } = window.location;
|
|
@@ -63,14 +71,16 @@ const getCurrentPageUrl = (): string | undefined => {
|
|
|
63
71
|
return `${origin}${pathname || ""}`;
|
|
64
72
|
})();
|
|
65
73
|
|
|
66
|
-
// Top window —
|
|
67
|
-
if (window === window.top)
|
|
74
|
+
// Top window — no iframe distinction, report the local URL only.
|
|
75
|
+
if (window === window.top) {
|
|
76
|
+
return { currentUrl: local, iframeUrl: undefined };
|
|
77
|
+
}
|
|
68
78
|
|
|
69
79
|
// Same-origin iframe — read the top URL directly.
|
|
70
80
|
try {
|
|
71
81
|
const topHref = window.top?.location?.href;
|
|
72
82
|
const sanitised = topHref ? sanitiseHref(topHref) : undefined;
|
|
73
|
-
if (sanitised) return sanitised;
|
|
83
|
+
if (sanitised) return { currentUrl: sanitised, iframeUrl: local };
|
|
74
84
|
} catch {
|
|
75
85
|
/* cross-origin — fall through */
|
|
76
86
|
}
|
|
@@ -79,10 +89,13 @@ const getCurrentPageUrl = (): string | undefined => {
|
|
|
79
89
|
// subject to the parent's Referrer-Policy header.
|
|
80
90
|
if (typeof document !== "undefined" && document.referrer) {
|
|
81
91
|
const fromReferrer = sanitiseHref(document.referrer);
|
|
82
|
-
if (fromReferrer) return fromReferrer;
|
|
92
|
+
if (fromReferrer) return { currentUrl: fromReferrer, iframeUrl: local };
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
|
|
95
|
+
// Referrer unavailable — fall back to the iframe URL for `currentUrl` so
|
|
96
|
+
// the provider still sees a value, and echo it as `iframeUrl` so
|
|
97
|
+
// downstream can tell the top frame was not observed.
|
|
98
|
+
return { currentUrl: local, iframeUrl: local };
|
|
86
99
|
};
|
|
87
100
|
|
|
88
101
|
export const withTimeout = async <T>(
|
|
@@ -165,6 +178,7 @@ const customDetectBot: BotDetectionFunction = async (
|
|
|
165
178
|
// lets it complete in the worker thread while the network round-trip
|
|
166
179
|
// burns. Readings still attach on the challenge GET and on solution
|
|
167
180
|
// submit (first-hop-wins server-side).
|
|
181
|
+
const { currentUrl, iframeUrl } = getCurrentPageUrls();
|
|
168
182
|
const captchaPromise = providerApi.getFrictionlessCaptcha(
|
|
169
183
|
detectionResult.token,
|
|
170
184
|
detectionResult.encryptHeadHash,
|
|
@@ -172,7 +186,8 @@ const customDetectBot: BotDetectionFunction = async (
|
|
|
172
186
|
userAccount.account.address,
|
|
173
187
|
config.mode,
|
|
174
188
|
undefined,
|
|
175
|
-
|
|
189
|
+
currentUrl,
|
|
190
|
+
iframeUrl,
|
|
176
191
|
);
|
|
177
192
|
if (detectionResult.getSimdReadings) {
|
|
178
193
|
// Fire-and-forget: triggers the memoised prefetch inside the catcher
|
|
@@ -93,7 +93,7 @@ describe("customDetectBot SIMD deferral", () => {
|
|
|
93
93
|
|
|
94
94
|
expect(mocks.getFrictionlessCaptcha).toHaveBeenCalledTimes(1);
|
|
95
95
|
const args = mocks.getFrictionlessCaptcha.mock.calls[0];
|
|
96
|
-
// args: token, headHash, dappAccount, userAccount, mode, simdReadings, currentUrl
|
|
96
|
+
// args: token, headHash, dappAccount, userAccount, mode, simdReadings, currentUrl, iframeUrl
|
|
97
97
|
expect(args?.[5]).toBeUndefined();
|
|
98
98
|
});
|
|
99
99
|
|