@prosopo/provider 5.14.0 → 5.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$cjs.log +62 -46
- package/.turbo/turbo-build$colon$tsc.log +37 -34
- package/.turbo/turbo-build.log +63 -50
- package/CHANGELOG.md +193 -0
- package/LICENSE +201 -0
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts +4 -0
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +63 -3
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js.map +1 -1
- package/dist/api/blacklistRequestInspector.js +2 -2
- package/dist/api/captcha/getAudioCaptchaChallenge.d.ts +5 -0
- package/dist/api/captcha/getAudioCaptchaChallenge.d.ts.map +1 -0
- package/dist/api/captcha/getAudioCaptchaChallenge.js +37 -0
- package/dist/api/captcha/getAudioCaptchaChallenge.js.map +1 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts +2 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -2
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +26 -15
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts +5 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts.map +1 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js +20 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js.map +1 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts.map +1 -1
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +1 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js.map +1 -1
- package/dist/api/captcha/getIconOrderCaptchaChallenge.d.ts +5 -0
- package/dist/api/captcha/getIconOrderCaptchaChallenge.d.ts.map +1 -0
- package/dist/api/captcha/getIconOrderCaptchaChallenge.js +37 -0
- package/dist/api/captcha/getIconOrderCaptchaChallenge.js.map +1 -0
- package/dist/api/captcha/getImageCaptchaChallenge.js +2 -2
- package/dist/api/captcha/getPoWCaptchaChallenge.js +4 -4
- package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts +1 -3
- package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js +53 -146
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
- package/dist/api/captcha/interactiveCaptchaChallenge.d.ts +42 -0
- package/dist/api/captcha/interactiveCaptchaChallenge.d.ts.map +1 -0
- package/dist/api/captcha/interactiveCaptchaChallenge.js +154 -0
- package/dist/api/captcha/interactiveCaptchaChallenge.js.map +1 -0
- package/dist/api/captcha/interactiveCaptchaSolution.d.ts +14 -0
- package/dist/api/captcha/interactiveCaptchaSolution.d.ts.map +1 -0
- package/dist/api/captcha/interactiveCaptchaSolution.js +77 -0
- package/dist/api/captcha/interactiveCaptchaSolution.js.map +1 -0
- package/dist/api/captcha/maintenanceModeResponses.d.ts +4 -2
- package/dist/api/captcha/maintenanceModeResponses.d.ts.map +1 -1
- package/dist/api/captcha/maintenanceModeResponses.js +28 -1
- package/dist/api/captcha/maintenanceModeResponses.js.map +1 -1
- package/dist/api/captcha/submitAudioCaptchaSolution.d.ts +4 -0
- package/dist/api/captcha/submitAudioCaptchaSolution.d.ts.map +1 -0
- package/dist/api/captcha/submitAudioCaptchaSolution.js +11 -0
- package/dist/api/captcha/submitAudioCaptchaSolution.js.map +1 -0
- package/dist/api/captcha/submitIconOrderCaptchaSolution.d.ts +4 -0
- package/dist/api/captcha/submitIconOrderCaptchaSolution.d.ts.map +1 -0
- package/dist/api/captcha/submitIconOrderCaptchaSolution.js +11 -0
- package/dist/api/captcha/submitIconOrderCaptchaSolution.js.map +1 -0
- package/dist/api/captcha/submitPoWCaptchaSolution.d.ts +4 -11
- package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
- package/dist/api/captcha/submitPoWCaptchaSolution.js +13 -18
- package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
- package/dist/api/captcha/submitPuzzleCaptchaSolution.d.ts +1 -3
- package/dist/api/captcha/submitPuzzleCaptchaSolution.d.ts.map +1 -1
- package/dist/api/captcha/submitPuzzleCaptchaSolution.js +6 -73
- package/dist/api/captcha/submitPuzzleCaptchaSolution.js.map +1 -1
- package/dist/api/captcha/trafficFilterRequestTime.d.ts +4 -1
- package/dist/api/captcha/trafficFilterRequestTime.d.ts.map +1 -1
- package/dist/api/captcha/trafficFilterRequestTime.js +3 -0
- package/dist/api/captcha/trafficFilterRequestTime.js.map +1 -1
- package/dist/api/captcha.d.ts.map +1 -1
- package/dist/api/captcha.js +8 -0
- package/dist/api/captcha.js.map +1 -1
- package/dist/api/domainMiddleware.js +1 -1
- package/dist/api/ja4Middleware.js +1 -1
- package/dist/api/rawTlsSignalsMiddleware.d.ts +14 -1
- package/dist/api/rawTlsSignalsMiddleware.d.ts.map +1 -1
- package/dist/api/rawTlsSignalsMiddleware.js +111 -23
- package/dist/api/rawTlsSignalsMiddleware.js.map +1 -1
- package/dist/api/startProviderApi.js +2 -2
- package/dist/api/verify.d.ts.map +1 -1
- package/dist/api/verify.js +153 -96
- package/dist/api/verify.js.map +1 -1
- package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +65 -2
- package/dist/cjs/api/blacklistRequestInspector.cjs +2 -2
- package/dist/cjs/api/captcha/getAudioCaptchaChallenge.cjs +37 -0
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -0
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +1 -1
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +25 -14
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.cjs +20 -0
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +1 -0
- package/dist/cjs/api/captcha/getIconOrderCaptchaChallenge.cjs +37 -0
- package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +2 -2
- package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +4 -4
- package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +52 -145
- package/dist/cjs/api/captcha/interactiveCaptchaChallenge.cjs +154 -0
- package/dist/cjs/api/captcha/interactiveCaptchaSolution.cjs +77 -0
- package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +29 -0
- package/dist/cjs/api/captcha/submitAudioCaptchaSolution.cjs +11 -0
- package/dist/cjs/api/captcha/submitIconOrderCaptchaSolution.cjs +11 -0
- package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +11 -16
- package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +6 -73
- package/dist/cjs/api/captcha/trafficFilterRequestTime.cjs +3 -0
- package/dist/cjs/api/captcha.cjs +8 -0
- package/dist/cjs/api/domainMiddleware.cjs +1 -1
- package/dist/cjs/api/ja4Middleware.cjs +1 -1
- package/dist/cjs/api/rawTlsSignalsMiddleware.cjs +111 -22
- package/dist/cjs/api/startProviderApi.cjs +2 -2
- package/dist/cjs/api/verify.cjs +152 -95
- package/dist/cjs/compositeIpAddress.cjs +21 -7
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/tasks/audio/audioBuffer.cjs +72 -0
- package/dist/cjs/tasks/audio/audioRenderer.cjs +32 -0
- package/dist/cjs/tasks/audioAlternative.cjs +23 -0
- package/dist/cjs/tasks/audioCaptcha/audioTasks.cjs +65 -0
- package/dist/cjs/tasks/audioCaptcha/audioTasksUtils.cjs +19 -0
- package/dist/cjs/tasks/captchaManager.cjs +28 -1
- package/dist/cjs/tasks/captchaTypeSelection.cjs +31 -3
- package/dist/cjs/tasks/client/clientTasks.cjs +2 -2
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +49 -26
- package/dist/cjs/tasks/iconOrder/iconOrderRenderer.cjs +42 -0
- package/dist/cjs/tasks/iconOrderCaptcha/iconOrderTasks.cjs +69 -0
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +10 -17
- package/dist/cjs/tasks/interactiveCaptcha/interactiveCaptchaManager.cjs +423 -0
- package/dist/cjs/tasks/powCaptcha/powTasks.cjs +15 -19
- package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +3 -1
- package/dist/cjs/tasks/puzzle/backgroundBuffer.cjs +3 -3
- package/dist/cjs/tasks/puzzle/nativeBackground.cjs +12 -5
- package/dist/cjs/tasks/puzzle/puzzleRenderer.cjs +4 -3
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +40 -493
- package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +18 -1
- package/dist/cjs/tasks/tasks.cjs +6 -0
- package/dist/cjs/util.cjs +1 -1
- package/dist/compositeIpAddress.d.ts.map +1 -1
- package/dist/compositeIpAddress.js +21 -7
- package/dist/compositeIpAddress.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/tasks/audio/audioBuffer.d.ts +23 -0
- package/dist/tasks/audio/audioBuffer.d.ts.map +1 -0
- package/dist/tasks/audio/audioBuffer.js +70 -0
- package/dist/tasks/audio/audioBuffer.js.map +1 -0
- package/dist/tasks/audio/audioRenderer.d.ts +11 -0
- package/dist/tasks/audio/audioRenderer.d.ts.map +1 -0
- package/dist/tasks/audio/audioRenderer.js +31 -0
- package/dist/tasks/audio/audioRenderer.js.map +1 -0
- package/dist/tasks/audioAlternative.d.ts +8 -0
- package/dist/tasks/audioAlternative.d.ts.map +1 -0
- package/dist/tasks/audioAlternative.js +20 -0
- package/dist/tasks/audioAlternative.js.map +1 -0
- package/dist/tasks/audioCaptcha/audioTasks.d.ts +19 -0
- package/dist/tasks/audioCaptcha/audioTasks.d.ts.map +1 -0
- package/dist/tasks/audioCaptcha/audioTasks.js +65 -0
- package/dist/tasks/audioCaptcha/audioTasks.js.map +1 -0
- package/dist/tasks/audioCaptcha/audioTasksUtils.d.ts +3 -0
- package/dist/tasks/audioCaptcha/audioTasksUtils.d.ts.map +1 -0
- package/dist/tasks/audioCaptcha/audioTasksUtils.js +18 -0
- package/dist/tasks/audioCaptcha/audioTasksUtils.js.map +1 -0
- package/dist/tasks/captchaManager.d.ts +9 -3
- package/dist/tasks/captchaManager.d.ts.map +1 -1
- package/dist/tasks/captchaManager.js +29 -2
- package/dist/tasks/captchaManager.js.map +1 -1
- package/dist/tasks/captchaTypeSelection.d.ts +4 -2
- package/dist/tasks/captchaTypeSelection.d.ts.map +1 -1
- package/dist/tasks/captchaTypeSelection.js +32 -5
- package/dist/tasks/captchaTypeSelection.js.map +1 -1
- package/dist/tasks/client/clientTasks.js +2 -2
- package/dist/tasks/frictionless/frictionlessTasks.d.ts +6 -1
- package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +1 -1
- package/dist/tasks/frictionless/frictionlessTasks.js +51 -28
- package/dist/tasks/frictionless/frictionlessTasks.js.map +1 -1
- package/dist/tasks/frictionless/routingMachine.d.ts +1 -2
- package/dist/tasks/frictionless/routingMachine.d.ts.map +1 -1
- package/dist/tasks/frictionless/routingMachine.js.map +1 -1
- package/dist/tasks/iconOrder/iconOrderRenderer.d.ts +12 -0
- package/dist/tasks/iconOrder/iconOrderRenderer.d.ts.map +1 -0
- package/dist/tasks/iconOrder/iconOrderRenderer.js +40 -0
- package/dist/tasks/iconOrder/iconOrderRenderer.js.map +1 -0
- package/dist/tasks/iconOrderCaptcha/iconOrderTasks.d.ts +22 -0
- package/dist/tasks/iconOrderCaptcha/iconOrderTasks.d.ts.map +1 -0
- package/dist/tasks/iconOrderCaptcha/iconOrderTasks.js +69 -0
- package/dist/tasks/iconOrderCaptcha/iconOrderTasks.js.map +1 -0
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +10 -17
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
- package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts +52 -0
- package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts.map +1 -0
- package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js +423 -0
- package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js.map +1 -0
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.js +15 -19
- package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
- package/dist/tasks/powCaptcha/powTasksUtils.d.ts +1 -0
- package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasksUtils.js +3 -2
- package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
- package/dist/tasks/puzzle/backgroundBuffer.d.ts +3 -2
- package/dist/tasks/puzzle/backgroundBuffer.d.ts.map +1 -1
- package/dist/tasks/puzzle/backgroundBuffer.js +3 -3
- package/dist/tasks/puzzle/backgroundBuffer.js.map +1 -1
- package/dist/tasks/puzzle/nativeBackground.d.ts +5 -1
- package/dist/tasks/puzzle/nativeBackground.d.ts.map +1 -1
- package/dist/tasks/puzzle/nativeBackground.js +12 -5
- package/dist/tasks/puzzle/nativeBackground.js.map +1 -1
- package/dist/tasks/puzzle/puzzleRenderer.d.ts +2 -0
- package/dist/tasks/puzzle/puzzleRenderer.d.ts.map +1 -1
- package/dist/tasks/puzzle/puzzleRenderer.js +4 -3
- package/dist/tasks/puzzle/puzzleRenderer.js.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts +14 -16
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js +41 -494
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.d.ts +4 -1
- package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.js +18 -1
- package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
- package/dist/tasks/tasks.d.ts +4 -0
- package/dist/tasks/tasks.d.ts.map +1 -1
- package/dist/tasks/tasks.js +6 -0
- package/dist/tasks/tasks.js.map +1 -1
- package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js +7 -3
- package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js.map +1 -1
- package/dist/tests/integration/clientSettingsPersistence.integration.test.js +44 -2
- package/dist/tests/integration/clientSettingsPersistence.integration.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js +4 -2
- package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js +76 -1
- package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js +54 -2
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts +2 -0
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js +45 -0
- package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js.map +1 -0
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +20 -0
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js +15 -1
- package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js.map +1 -1
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +174 -0
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
- package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js +96 -1
- package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js.map +1 -1
- package/dist/tests/unit/compositeIpAddress.unit.test.js +12 -3
- package/dist/tests/unit/compositeIpAddress.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.js +105 -0
- package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/audioAlternative.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/audioAlternative.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/audioAlternative.unit.test.js +76 -0
- package/dist/tests/unit/tasks/audioAlternative.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.js +259 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.js +52 -0
- package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/captchaManager.unit.test.js +171 -2
- package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js +68 -6
- package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js +123 -0
- package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js +31 -0
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js +103 -0
- package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/frictionless/routerPuzzleOverrides.unit.test.js +28 -0
- package/dist/tests/unit/tasks/frictionless/routerPuzzleOverrides.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.js +60 -0
- package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.js +225 -0
- package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +23 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js +1 -4
- package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js +10 -3
- package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js +35 -0
- package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js.map +1 -0
- package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts +2 -0
- package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts.map +1 -0
- package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js +49 -0
- package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js.map +1 -0
- package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +17 -14
- package/dist/tests/unit/testUtils/mockProviderEnv.d.ts.map +1 -1
- package/dist/tests/unit/testUtils/mockProviderEnv.js.map +1 -1
- package/dist/util.js +1 -1
- package/package.json +107 -103
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
const require_usageCounters = require("../../util/usageCounters.cjs");
|
|
2
|
+
const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
|
|
3
|
+
const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
|
|
4
|
+
const require_util = require("../../util.cjs");
|
|
5
|
+
const require_clientMetaData = require("../../utils/clientMetaData.cjs");
|
|
6
|
+
const require_devicePlatform = require("../../utils/devicePlatform.cjs");
|
|
7
|
+
const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
8
|
+
const require_captchaManager = require("../captchaManager.cjs");
|
|
9
|
+
const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
10
|
+
const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
11
|
+
const require_powTasksUtils = require("../powCaptcha/powTasksUtils.cjs");
|
|
12
|
+
const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
13
|
+
let _prosopo_common = require("@prosopo/common");
|
|
14
|
+
let _prosopo_types = require("@prosopo/types");
|
|
15
|
+
let _polkadot_util = require("@polkadot/util");
|
|
16
|
+
let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
|
|
17
|
+
let _prosopo_util = require("@prosopo/util");
|
|
18
|
+
//#region src/tasks/interactiveCaptcha/interactiveCaptchaManager.ts
|
|
19
|
+
/**
|
|
20
|
+
* Shared pipeline for the captcha types a human solves on screen (puzzle,
|
|
21
|
+
* icon-order). Subclasses supply the record accessors and grading; minting,
|
|
22
|
+
* submission bookkeeping and server verification live here.
|
|
23
|
+
*/
|
|
24
|
+
var InteractiveCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
25
|
+
constructor(db, pair, config, logger, usageCounters) {
|
|
26
|
+
super(db, pair, config, logger);
|
|
27
|
+
this.POW_SEPARATOR = _prosopo_types.POW_SEPARATOR;
|
|
28
|
+
this.decisionMachineRunner = new require_decisionMachineRunner.DecisionMachineRunner(db);
|
|
29
|
+
this.usageCounters = usageCounters ?? null;
|
|
30
|
+
}
|
|
31
|
+
mintChallenge(userAccount, dappAccount) {
|
|
32
|
+
const requestedAtTimestamp = Date.now();
|
|
33
|
+
const challenge = `${requestedAtTimestamp}___${userAccount}___${dappAccount}___${Math.floor(Math.random() * 1e6)}`;
|
|
34
|
+
return {
|
|
35
|
+
challenge,
|
|
36
|
+
providerSignature: (0, _polkadot_util.u8aToHex)(this.pair.sign((0, _polkadot_util.stringToHex)(challenge))),
|
|
37
|
+
requestedAtTimestamp
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Grades a user's submission and records the outcome on the captcha and
|
|
42
|
+
* session records. Returns whether the solution was correct.
|
|
43
|
+
*/
|
|
44
|
+
async submitInteractiveCaptchaSolution(submission) {
|
|
45
|
+
const { challenge, userTimestampSignature, behavioralData, simdReadings } = submission;
|
|
46
|
+
require_powTasksUtils.checkPowSignature(challenge, submission.providerChallengeSignature, this.pair.address, _prosopo_types.ApiParams.challenge);
|
|
47
|
+
const challengeSplit = challenge.split(this.POW_SEPARATOR);
|
|
48
|
+
const timestamp = Number.parseInt((0, _prosopo_util.at)(challengeSplit, 0));
|
|
49
|
+
const userAccount = (0, _prosopo_util.at)(challengeSplit, 1);
|
|
50
|
+
require_powTasksUtils.checkPowSignature(timestamp.toString(), userTimestampSignature, userAccount, _prosopo_types.ApiParams.timestamp);
|
|
51
|
+
const challengeRecord = await this.getRecordByChallenge(challenge);
|
|
52
|
+
if (!challengeRecord) {
|
|
53
|
+
this.logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const { coords, saltDecodeError } = this.decodeSaltCoords(submission.salt);
|
|
57
|
+
if (!await this.claimSubmission(challengeRecord)) {
|
|
58
|
+
this.logger.debug(() => ({ msg: `Challenge already submitted: ${challenge}` }));
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (saltDecodeError) {
|
|
62
|
+
await this.recordSubmissionResult(challengeRecord, {
|
|
63
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
64
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SALT
|
|
65
|
+
}, userTimestampSignature, void 0);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (!(0, _prosopo_util.verifyRecency)(challenge, submission.timeout)) {
|
|
69
|
+
await this.recordSubmissionResult(challengeRecord, {
|
|
70
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
71
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_TIMESTAMP
|
|
72
|
+
}, userTimestampSignature, coords);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const correct = submission.isCorrect(challengeRecord);
|
|
76
|
+
const result = correct ? { status: _prosopo_types.CaptchaStatus.approved } : {
|
|
77
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
78
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SOLUTION
|
|
79
|
+
};
|
|
80
|
+
if (correct && this.usageCounters) this.usageCounters.incrManyAsync((0, _prosopo_util.at)(challengeSplit, 2), require_usageCounters.buildAllWindowIncrements("solved", this.captchaType, submission.ipAddress.address, userAccount));
|
|
81
|
+
await submission.persistInteraction();
|
|
82
|
+
const decodedPayloads = await this.decodeSubmissionPayloads(challengeRecord.sessionId, {
|
|
83
|
+
behavioural: behavioralData,
|
|
84
|
+
simd: simdReadings
|
|
85
|
+
});
|
|
86
|
+
if (behavioralData) try {
|
|
87
|
+
const decryptedData = decodedPayloads.behavioural;
|
|
88
|
+
if (decryptedData) {
|
|
89
|
+
this.logger?.info(() => ({
|
|
90
|
+
msg: "Behavioral analysis completed",
|
|
91
|
+
data: {
|
|
92
|
+
userAccount,
|
|
93
|
+
dappAccount: (0, _prosopo_util.at)(challengeSplit, 2),
|
|
94
|
+
challenge,
|
|
95
|
+
mouseEventsCount: decryptedData.collector1?.length || 0,
|
|
96
|
+
touchEventsCount: decryptedData.collector2?.length || 0,
|
|
97
|
+
clickEventsCount: decryptedData.collector3?.length || 0,
|
|
98
|
+
scrollEventsCount: decryptedData.collector4?.length || 0,
|
|
99
|
+
deviceCapability: decryptedData.deviceCapability,
|
|
100
|
+
captchaResult: correct ? "passed" : "failed"
|
|
101
|
+
}
|
|
102
|
+
}));
|
|
103
|
+
const packedData = {
|
|
104
|
+
c1: decryptedData.collector1 || [],
|
|
105
|
+
c2: decryptedData.collector2 || [],
|
|
106
|
+
c3: decryptedData.collector3 || [],
|
|
107
|
+
c4: decryptedData.collector4 || [],
|
|
108
|
+
d: decryptedData.deviceCapability
|
|
109
|
+
};
|
|
110
|
+
await this.updateRecord(challenge, {
|
|
111
|
+
behavioralDataPacked: packedData,
|
|
112
|
+
deviceCapability: decryptedData.deviceCapability
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.logger?.error(() => ({
|
|
117
|
+
msg: "Failed to process behavioral data",
|
|
118
|
+
err: error
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
const storedClientMetaData = require_clientMetaData.toStoredClientMetaData(submission.clientMetaData);
|
|
122
|
+
if (storedClientMetaData) await this.updateRecord(challenge, { clientMetaData: storedClientMetaData });
|
|
123
|
+
await this.recordSubmissionResult(challengeRecord, result, userTimestampSignature, coords, storedClientMetaData);
|
|
124
|
+
if (challengeRecord.sessionId && decodedPayloads.simd) await this.recordSessionSimdReadingsIfAbsentWithCache(challengeRecord.sessionId, decodedPayloads.simd, _prosopo_types.SimdReadingsStage.submit);
|
|
125
|
+
return correct;
|
|
126
|
+
}
|
|
127
|
+
/** Invalid salt disapproves the submission rather than being ignored. */
|
|
128
|
+
decodeSaltCoords(salt) {
|
|
129
|
+
if (!salt) return {};
|
|
130
|
+
try {
|
|
131
|
+
const extractedData = (0, _prosopo_util.extractData)(salt);
|
|
132
|
+
if (extractedData.length < 2) return {};
|
|
133
|
+
const coords = [[[extractedData[0], extractedData[1]]]];
|
|
134
|
+
(0, _prosopo_util.assertCoordsSafe)(coords, "coords");
|
|
135
|
+
return { coords };
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.logger.warn(() => ({
|
|
138
|
+
msg: "Failed to extract coordinates from salt",
|
|
139
|
+
error,
|
|
140
|
+
salt
|
|
141
|
+
}));
|
|
142
|
+
return { saltDecodeError: error };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async recordSubmissionResult(challengeRecord, result, userSignature, coords, clientMetaData) {
|
|
146
|
+
await this.updateSubmissionResult(challengeRecord.challenge, result, userSignature, coords);
|
|
147
|
+
if (challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
148
|
+
userSubmitted: true,
|
|
149
|
+
result,
|
|
150
|
+
...(0, _prosopo_types.isBlockingCaptchaResult)(this.captchaType, result) && { blocked: true },
|
|
151
|
+
...clientMetaData && { clientMetaData }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The post-solve gate the site's server calls: decides whether the token
|
|
156
|
+
* the widget was given is honoured.
|
|
157
|
+
*
|
|
158
|
+
* @param dappAccount - the dapp that is requesting the captcha
|
|
159
|
+
* @param challenge - the challenge string
|
|
160
|
+
* @param timeout - milliseconds allowed between submit and verify
|
|
161
|
+
* @param env - provider environment
|
|
162
|
+
* @param ip - optional IP address for validation
|
|
163
|
+
* @param userAccessRulesStorage - storage for querying user access policies
|
|
164
|
+
* @param email
|
|
165
|
+
* @param spamEmailDomainCheckingEnabled
|
|
166
|
+
* @param spamFilter
|
|
167
|
+
* @param trafficFilter
|
|
168
|
+
* @param storeMetadata - when true, persists the dapp-server-provided
|
|
169
|
+
* `email` on the captcha record for spam-rate analysis.
|
|
170
|
+
* @param clientSessionId - the session id the site rendered the widget
|
|
171
|
+
* with. When supplied, the solve must carry the same value in its
|
|
172
|
+
* `clientMetaData` or it is disapproved.
|
|
173
|
+
*/
|
|
174
|
+
async serverVerifyInteractiveCaptchaSolution(dappAccount, challenge, timeout, env, ip, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false, clientSessionId) {
|
|
175
|
+
const notVerifiedResponse = { verified: false };
|
|
176
|
+
const logger = this.logger.with({
|
|
177
|
+
challenge,
|
|
178
|
+
dappAccount
|
|
179
|
+
});
|
|
180
|
+
const challengeRecord = await this.getRecordByChallenge(challenge);
|
|
181
|
+
if (!challengeRecord) {
|
|
182
|
+
logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
|
|
183
|
+
return notVerifiedResponse;
|
|
184
|
+
}
|
|
185
|
+
notVerifiedResponse.sessionId = challengeRecord.sessionId;
|
|
186
|
+
if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoApiError("CAPTCHA.INVALID_SOLUTION", { context: {
|
|
187
|
+
code: 400,
|
|
188
|
+
failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
|
|
189
|
+
challenge
|
|
190
|
+
} });
|
|
191
|
+
if (challengeRecord.serverChecked) return notVerifiedResponse;
|
|
192
|
+
const challengeDappAccount = challengeRecord.dappAccount;
|
|
193
|
+
if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", { context: {
|
|
194
|
+
failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
|
|
195
|
+
dappAccount,
|
|
196
|
+
challengeDappAccount
|
|
197
|
+
} });
|
|
198
|
+
if (!await this.markRecordChecked(challengeRecord.challenge)) return notVerifiedResponse;
|
|
199
|
+
const submittedAt = challengeRecord.submittedAtTimestamp;
|
|
200
|
+
if ((submittedAt instanceof Date ? Date.now() - submittedAt.getTime() : Number.POSITIVE_INFINITY) > timeout) {
|
|
201
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.TIMESTAMP_TOO_OLD);
|
|
202
|
+
return notVerifiedResponse;
|
|
203
|
+
}
|
|
204
|
+
if (require_clientMetaData.isClientSessionMismatch(clientSessionId, challengeRecord.clientMetaData?.clientSessionId)) {
|
|
205
|
+
logger.info(() => ({
|
|
206
|
+
msg: `Client session mismatch in server ${this.logLabel} verification`,
|
|
207
|
+
data: { hasRecordedClientSessionId: Boolean(challengeRecord.clientMetaData?.clientSessionId) }
|
|
208
|
+
}));
|
|
209
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.CLIENT_SESSION_MISMATCH);
|
|
210
|
+
return notVerifiedResponse;
|
|
211
|
+
}
|
|
212
|
+
if (userAccessRulesStorage) try {
|
|
213
|
+
const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, challengeRecord, challengeRecord.userAccount, challengeRecord.headers, challengeRecord.coords, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.asnNumber : void 0);
|
|
214
|
+
if (blockPolicy) {
|
|
215
|
+
logger.info(() => ({
|
|
216
|
+
msg: `User blocked by access policy in server ${this.logLabel} verification`,
|
|
217
|
+
data: {
|
|
218
|
+
userAccount: challengeRecord.userAccount,
|
|
219
|
+
policy: blockPolicy
|
|
220
|
+
}
|
|
221
|
+
}));
|
|
222
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.ACCESS_POLICY_BLOCK, { matchedRule: (0, _prosopo_user_access_policy.describeMatchedRule)(blockPolicy) });
|
|
223
|
+
return notVerifiedResponse;
|
|
224
|
+
}
|
|
225
|
+
} catch (error) {
|
|
226
|
+
logger.warn(() => ({
|
|
227
|
+
msg: `Failed to check user access policies in server ${this.logLabel} verification`,
|
|
228
|
+
error
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
if (email && spamEmailDomainCheckingEnabled) try {
|
|
232
|
+
if (await this.checkSpamEmail(email)) {
|
|
233
|
+
const emailDomain = email.split("@")[1] || "unknown";
|
|
234
|
+
logger.info(() => ({
|
|
235
|
+
msg: `Spam email domain detected in server ${this.logLabel} verification`,
|
|
236
|
+
data: { emailDomain }
|
|
237
|
+
}));
|
|
238
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.SPAM_EMAIL_DOMAIN, null);
|
|
239
|
+
return notVerifiedResponse;
|
|
240
|
+
}
|
|
241
|
+
} catch (error) {
|
|
242
|
+
logger.warn(() => ({
|
|
243
|
+
msg: `Failed to check spam email domain in server ${this.logLabel} verification`,
|
|
244
|
+
error
|
|
245
|
+
}));
|
|
246
|
+
}
|
|
247
|
+
const maxEmailSubmissionCount = spamFilter?.enabled && spamFilter.emailRules?.enabled ? spamFilter.emailRules.maxEmailSubmissionCount : void 0;
|
|
248
|
+
let emailNormalised;
|
|
249
|
+
if (maxEmailSubmissionCount !== void 0 && email && storeMetadata) {
|
|
250
|
+
emailNormalised = require_evaluateEmailSpamRules.normaliseEmailForMatching(email);
|
|
251
|
+
if (emailNormalised) try {
|
|
252
|
+
const priorCount = await this.db.countCommitmentsByNormalisedEmail(dappAccount, emailNormalised);
|
|
253
|
+
if (priorCount >= maxEmailSubmissionCount) {
|
|
254
|
+
logger.info(() => ({
|
|
255
|
+
msg: `Email submission count exceeded in server ${this.logLabel} verification`,
|
|
256
|
+
data: {
|
|
257
|
+
priorCount,
|
|
258
|
+
maxEmailSubmissionCount
|
|
259
|
+
}
|
|
260
|
+
}));
|
|
261
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.SPAM_EMAIL_COUNT_EXCEEDED, null);
|
|
262
|
+
return notVerifiedResponse;
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
logger.warn(() => ({
|
|
266
|
+
msg: `Failed to check email submission count in server ${this.logLabel} verification`,
|
|
267
|
+
error
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const sessionRecord = challengeRecord.sessionId ? await this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : void 0;
|
|
272
|
+
const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip);
|
|
273
|
+
{
|
|
274
|
+
const check = await this.resolveTrafficFilterCheck(env, challengeRecord.ipInfo, trafficFilter, ip, enrichedDnsEvent);
|
|
275
|
+
if (check.isBlocked) {
|
|
276
|
+
logger.info(() => ({
|
|
277
|
+
msg: `Traffic filter rejected request in ${this.logLabel} verification`,
|
|
278
|
+
data: {
|
|
279
|
+
ip,
|
|
280
|
+
reason: check.reason,
|
|
281
|
+
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
282
|
+
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
283
|
+
dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
284
|
+
dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
285
|
+
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
286
|
+
}
|
|
287
|
+
}));
|
|
288
|
+
await this.disapproveVerification(challengeRecord, check.reason);
|
|
289
|
+
return notVerifiedResponse;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (storeMetadata && email) await this.updateRecord(challengeRecord.challenge, { metadata: {
|
|
293
|
+
email,
|
|
294
|
+
emailNormalised: emailNormalised ?? require_evaluateEmailSpamRules.normaliseEmailForMatching(email)
|
|
295
|
+
} });
|
|
296
|
+
if (ip) {
|
|
297
|
+
const challengeIpAddress = require_compositeIpAddress.getIpAddressFromComposite(challengeRecord.ipAddress);
|
|
298
|
+
const ipValidationRules = (await this.db.getClientRecord(dappAccount))?.settings?.ipValidationRules;
|
|
299
|
+
await this.updateRecord(challengeRecord.challenge, { providedIp: require_compositeIpAddress.getCompositeIpAddress(ip) });
|
|
300
|
+
if (ipValidationRules?.enabled === true) {
|
|
301
|
+
const ipValidation = await require_util.deepValidateIpAddress(ip, challengeIpAddress, logger, env.ipInfoService, ipValidationRules, enrichedDnsEvent?.peerIp);
|
|
302
|
+
if (!ipValidation.isValid) {
|
|
303
|
+
logger.error(() => ({
|
|
304
|
+
msg: `IP validation failed for ${this.logLabel} captcha`,
|
|
305
|
+
data: {
|
|
306
|
+
ip,
|
|
307
|
+
challengeIp: challengeIpAddress.address,
|
|
308
|
+
error: ipValidation.errorMessage,
|
|
309
|
+
distanceKm: ipValidation.distanceKm
|
|
310
|
+
}
|
|
311
|
+
}));
|
|
312
|
+
await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.FAILED_IP_VALIDATION);
|
|
313
|
+
return notVerifiedResponse;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
let score;
|
|
318
|
+
if (sessionRecord) {
|
|
319
|
+
const dnsAsymmetry = require_enrichDnsEvent.computeDnsAsymmetry(enrichedDnsEvent, challengeRecord.ipInfo, trafficFilter);
|
|
320
|
+
if (dnsAsymmetry > 0) sessionRecord.scoreComponents = {
|
|
321
|
+
...sessionRecord.scoreComponents,
|
|
322
|
+
dnsAsymmetry
|
|
323
|
+
};
|
|
324
|
+
score = require_frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
325
|
+
logger.info(() => ({ data: {
|
|
326
|
+
scoreComponents: { ...sessionRecord?.scoreComponents || {} },
|
|
327
|
+
score,
|
|
328
|
+
dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
329
|
+
dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
330
|
+
} }));
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
const decisionInput = {
|
|
334
|
+
userAccount: challengeRecord.userAccount,
|
|
335
|
+
dappAccount: challengeRecord.dappAccount,
|
|
336
|
+
captchaResult: "passed",
|
|
337
|
+
headers: challengeRecord.headers,
|
|
338
|
+
captchaType: this.captchaType,
|
|
339
|
+
behavioralDataPacked: challengeRecord.behavioralDataPacked,
|
|
340
|
+
deviceCapability: challengeRecord.deviceCapability,
|
|
341
|
+
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
|
|
342
|
+
ipInfo: challengeRecord.ipInfo,
|
|
343
|
+
dnsEvent: enrichedDnsEvent,
|
|
344
|
+
score,
|
|
345
|
+
threshold: sessionRecord?.threshold,
|
|
346
|
+
scoreComponents: sessionRecord?.scoreComponents,
|
|
347
|
+
decryptedHeadHash: sessionRecord?.decryptedHeadHash,
|
|
348
|
+
userSitekeyIpHash: sessionRecord?.userSitekeyIpHash,
|
|
349
|
+
simdReadings: sessionRecord?.simdReadings,
|
|
350
|
+
d: sessionRecord?.d,
|
|
351
|
+
frictionlessReason: sessionRecord?.reason,
|
|
352
|
+
ruleType: sessionRecord?.ruleType,
|
|
353
|
+
webView: sessionRecord?.webView,
|
|
354
|
+
iFrame: sessionRecord?.iFrame,
|
|
355
|
+
currentUrl: sessionRecord?.currentUrl,
|
|
356
|
+
iframeUrl: sessionRecord?.iframeUrl,
|
|
357
|
+
coords: challengeRecord.coords,
|
|
358
|
+
...this.decisionMachineEventFields(challengeRecord),
|
|
359
|
+
...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
|
|
360
|
+
trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
|
|
361
|
+
};
|
|
362
|
+
const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
|
|
363
|
+
if (decision.decision === _prosopo_types.DecisionMachineDecision.Deny) {
|
|
364
|
+
logger.info(() => ({
|
|
365
|
+
msg: `Decision machine denied ${this.logLabel} captcha in server verification`,
|
|
366
|
+
data: {
|
|
367
|
+
userAccount: challengeRecord.userAccount,
|
|
368
|
+
reason: decision.reason,
|
|
369
|
+
score: decision.score,
|
|
370
|
+
tags: decision.tags
|
|
371
|
+
}
|
|
372
|
+
}));
|
|
373
|
+
await this.disapproveVerification(challengeRecord, decision.reason || _prosopo_types.ResultReason.CAPTCHA_DECISION_MACHINE_DENIED);
|
|
374
|
+
return notVerifiedResponse;
|
|
375
|
+
}
|
|
376
|
+
logger.debug(() => ({
|
|
377
|
+
msg: `Decision machine allowed ${this.logLabel} captcha`,
|
|
378
|
+
data: {
|
|
379
|
+
reason: decision.reason,
|
|
380
|
+
score: decision.score,
|
|
381
|
+
tags: decision.tags
|
|
382
|
+
}
|
|
383
|
+
}));
|
|
384
|
+
} catch (error) {
|
|
385
|
+
logger.error(() => ({
|
|
386
|
+
msg: `Failed to run decision machine in server ${this.logLabel} verification`,
|
|
387
|
+
err: error
|
|
388
|
+
}));
|
|
389
|
+
}
|
|
390
|
+
if (challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
391
|
+
serverChecked: true,
|
|
392
|
+
result: { status: _prosopo_types.CaptchaStatus.approved }
|
|
393
|
+
});
|
|
394
|
+
return {
|
|
395
|
+
verified: true,
|
|
396
|
+
...score ? { score } : {},
|
|
397
|
+
...challengeRecord.sessionId && { sessionId: challengeRecord.sessionId }
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Records a server-verification rejection on the captcha record and, unless
|
|
402
|
+
* `session` is null, on the linked session.
|
|
403
|
+
*/
|
|
404
|
+
async disapproveVerification(challengeRecord, reason, session = {}) {
|
|
405
|
+
const result = {
|
|
406
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
407
|
+
reason
|
|
408
|
+
};
|
|
409
|
+
const isBlocked = (0, _prosopo_types.isBlockingCaptchaResult)(this.captchaType, result);
|
|
410
|
+
await this.updateRecord(challengeRecord.challenge, {
|
|
411
|
+
result,
|
|
412
|
+
...isBlocked && { blocked: true }
|
|
413
|
+
});
|
|
414
|
+
if (session && challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
415
|
+
serverChecked: true,
|
|
416
|
+
result,
|
|
417
|
+
...isBlocked && { blocked: true },
|
|
418
|
+
...session
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
//#endregion
|
|
423
|
+
exports.InteractiveCaptchaManager = InteractiveCaptchaManager;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
const require_usageCounters = require("../../util/usageCounters.cjs");
|
|
2
|
-
const
|
|
3
|
-
const require_clientMetaData = require("../../utils/clientMetaData.cjs");
|
|
2
|
+
const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
|
|
4
3
|
const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
|
|
5
|
-
const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
6
|
-
const require_captchaManager = require("../captchaManager.cjs");
|
|
7
|
-
const require_routingMachine = require("../frictionless/routingMachine.cjs");
|
|
8
4
|
const require_util = require("../../util.cjs");
|
|
5
|
+
const require_clientMetaData = require("../../utils/clientMetaData.cjs");
|
|
9
6
|
const require_devicePlatform = require("../../utils/devicePlatform.cjs");
|
|
7
|
+
const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
8
|
+
const require_captchaManager = require("../captchaManager.cjs");
|
|
9
|
+
const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
10
10
|
const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
11
|
-
const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
12
11
|
const require_powTasksUtils = require("./powTasksUtils.cjs");
|
|
12
|
+
const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
13
|
+
const require_routingMachine = require("../frictionless/routingMachine.cjs");
|
|
13
14
|
let _prosopo_common = require("@prosopo/common");
|
|
14
15
|
let _prosopo_types = require("@prosopo/types");
|
|
15
|
-
let _prosopo_util = require("@prosopo/util");
|
|
16
|
-
let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
|
|
17
16
|
let _polkadot_util = require("@polkadot/util");
|
|
17
|
+
let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
|
|
18
|
+
let _prosopo_util = require("@prosopo/util");
|
|
18
19
|
//#region src/tasks/powCaptcha/powTasks.ts
|
|
19
20
|
var DEFAULT_POW_DIFFICULTY = 4;
|
|
20
21
|
var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
@@ -209,7 +210,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
|
209
210
|
let routingOutput = this.postPowContext ? await this.runPostPowRouting({
|
|
210
211
|
challengeRecord,
|
|
211
212
|
challengeSplit,
|
|
212
|
-
behavioralDataPacked: decryptedBehavioralDataPacked
|
|
213
|
+
behavioralDataPacked: decryptedBehavioralDataPacked,
|
|
214
|
+
coords
|
|
213
215
|
}) : void 0;
|
|
214
216
|
if ((escalateForMissingCoords || escalateForIpChange) && routingOutput?.captchaType !== _prosopo_types.CaptchaType.image && routingOutput?.captchaType !== _prosopo_types.CaptchaType.puzzle) routingOutput = {
|
|
215
217
|
captchaType: _prosopo_types.CaptchaType.image,
|
|
@@ -228,7 +230,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
|
228
230
|
*/
|
|
229
231
|
async runPostPowRouting(args) {
|
|
230
232
|
if (!this.postPowContext) return void 0;
|
|
231
|
-
const { challengeRecord, challengeSplit, behavioralDataPacked } = args;
|
|
233
|
+
const { challengeRecord, challengeSplit, behavioralDataPacked, coords } = args;
|
|
232
234
|
if (!challengeRecord.sessionId) {
|
|
233
235
|
this.logger.debug(() => ({ msg: "Skipping post-pow routing: PoW record has no linked session" }));
|
|
234
236
|
return;
|
|
@@ -259,6 +261,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
|
259
261
|
raw: {
|
|
260
262
|
...this.postPowContext.raw,
|
|
261
263
|
...behavioralDataPacked && { behavioralDataPacked },
|
|
264
|
+
...sessionRecord.mode && { mode: sessionRecord.mode },
|
|
265
|
+
coordsAllZero: require_powTasksUtils.isCoordsAllZero(coords),
|
|
262
266
|
...sessionRecord.simdReadings && { simd: sessionRecord.simdReadings },
|
|
263
267
|
...sessionRecord.currentUrl && { currentUrl: sessionRecord.currentUrl },
|
|
264
268
|
...sessionRecord.iframeUrl && { iframeUrl: sessionRecord.iframeUrl }
|
|
@@ -518,15 +522,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
|
518
522
|
currentUrl: sessionRecord?.currentUrl,
|
|
519
523
|
iframeUrl: sessionRecord?.iframeUrl,
|
|
520
524
|
coords: challengeRecord.coords,
|
|
521
|
-
|
|
522
|
-
synackNs: sessionRecord?.synackNs,
|
|
523
|
-
ackNs: sessionRecord?.ackNs,
|
|
524
|
-
observedTtl: sessionRecord?.observedTtl,
|
|
525
|
-
tcpMss: sessionRecord?.tcpMss,
|
|
526
|
-
tcpWscale: sessionRecord?.tcpWscale,
|
|
527
|
-
tcpOptsFlags: sessionRecord?.tcpOptsFlags,
|
|
528
|
-
tcpOptsOrder: sessionRecord?.tcpOptsOrder,
|
|
529
|
-
tcpWindow: sessionRecord?.tcpWindow,
|
|
525
|
+
...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
|
|
530
526
|
trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
|
|
531
527
|
};
|
|
532
528
|
const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
let _prosopo_common = require("@prosopo/common");
|
|
2
|
+
let _polkadot_util = require("@polkadot/util");
|
|
2
3
|
let _prosopo_util = require("@prosopo/util");
|
|
3
4
|
let _prosopo_util_crypto = require("@prosopo/util-crypto");
|
|
4
|
-
let _polkadot_util = require("@polkadot/util");
|
|
5
5
|
let _noble_hashes_sha2_js = require("@noble/hashes/sha2.js");
|
|
6
6
|
//#region src/tasks/powCaptcha/powTasksUtils.ts
|
|
7
7
|
var validateSolution = (nonce, challenge, difficulty) => (0, _prosopo_util.hashMeetsDifficulty)((0, _noble_hashes_sha2_js.sha256)(new TextEncoder().encode(nonce + challenge)), difficulty);
|
|
@@ -15,6 +15,8 @@ var checkPowSignature = (message, signature, address, signatureType) => {
|
|
|
15
15
|
signatureType
|
|
16
16
|
} });
|
|
17
17
|
};
|
|
18
|
+
var isCoordsAllZero = (coords) => coords !== void 0 && coords.length > 0 && coords.every((group) => group.length > 0 && group.every(([x, y]) => x === 0 && y === 0));
|
|
18
19
|
//#endregion
|
|
19
20
|
exports.checkPowSignature = checkPowSignature;
|
|
21
|
+
exports.isCoordsAllZero = isCoordsAllZero;
|
|
20
22
|
exports.validateSolution = validateSolution;
|
|
@@ -15,12 +15,12 @@ var createPuzzleBackgroundBuffer = (options = {}) => {
|
|
|
15
15
|
timer.unref?.();
|
|
16
16
|
return {
|
|
17
17
|
take() {
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
18
|
+
const background = ready.pop();
|
|
19
|
+
if (!background) {
|
|
20
20
|
starved++;
|
|
21
21
|
return require_nativeBackground.createBackgroundNative(geometry);
|
|
22
22
|
}
|
|
23
|
-
return
|
|
23
|
+
return background;
|
|
24
24
|
},
|
|
25
25
|
depth: () => ready.length,
|
|
26
26
|
starvations: () => starved,
|
|
@@ -15,15 +15,22 @@ var nativePuzzle = (() => {
|
|
|
15
15
|
* Byte-identical to `createBackground` from @prosopo/puzzle-assets given the
|
|
16
16
|
* same seed — the JS remains the reference implementation and the contract
|
|
17
17
|
* the differential test pins. Single-use is unchanged and still the caller's
|
|
18
|
-
* responsibility
|
|
19
|
-
*
|
|
18
|
+
* responsibility.
|
|
19
|
+
*
|
|
20
|
+
* The seed is returned so the challenge record can keep it and the portal can
|
|
21
|
+
* regenerate this background later. See the secrecy note in prng.ts for where
|
|
22
|
+
* it may and may not go.
|
|
20
23
|
*/
|
|
21
24
|
var createBackgroundNative = (geometry = _prosopo_puzzle_assets.DEFAULT_GEOMETRY) => {
|
|
22
25
|
const { width, height } = geometry;
|
|
26
|
+
const seed = (0, _prosopo_puzzle_assets.createSeed)();
|
|
23
27
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
image: {
|
|
29
|
+
data: require_metrics.measureSync("puzzle_background", () => nativePuzzle.generateBackground(seed, width, height)),
|
|
30
|
+
width,
|
|
31
|
+
height
|
|
32
|
+
},
|
|
33
|
+
seed
|
|
27
34
|
};
|
|
28
35
|
};
|
|
29
36
|
//#endregion
|
|
@@ -79,15 +79,16 @@ var isPuzzleRenderAvailable = () => {
|
|
|
79
79
|
};
|
|
80
80
|
var renderPuzzleImages = async (placement, settings = _prosopo_puzzle_assets.DEFAULT_RENDER_SETTINGS, pieceSize) => {
|
|
81
81
|
const background = (require_backgroundBuffer.getPuzzleBackgroundBuffer() ?? require_backgroundBuffer.initPuzzleBackgroundBuffer()).take();
|
|
82
|
-
|
|
83
|
-
const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background, placement, pieceSize !== void 0 ? {
|
|
82
|
+
const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background.image, placement, pieceSize !== void 0 ? {
|
|
84
83
|
..._prosopo_puzzle_assets.DEFAULT_GEOMETRY,
|
|
85
84
|
pieceSize
|
|
86
85
|
} : _prosopo_puzzle_assets.DEFAULT_GEOMETRY, settings));
|
|
87
86
|
return {
|
|
88
87
|
background: (0, _prosopo_puzzle_assets.toDataUri)(rendered.background),
|
|
89
88
|
piece: (0, _prosopo_puzzle_assets.toDataUri)(rendered.piece),
|
|
90
|
-
pieceSize: rendered.pieceSize
|
|
89
|
+
pieceSize: rendered.pieceSize,
|
|
90
|
+
backgroundSeed: background.seed.toString("hex"),
|
|
91
|
+
renderSeed: rendered.seed.toString("hex")
|
|
91
92
|
};
|
|
92
93
|
};
|
|
93
94
|
//#endregion
|