@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
package/dist/cjs/api/verify.cjs
CHANGED
|
@@ -3,13 +3,13 @@ const require_metrics = require("./metrics.cjs");
|
|
|
3
3
|
const require_tasks = require("../tasks/tasks.cjs");
|
|
4
4
|
const require_apiToggleMaintenanceModeEndpoint = require("./admin/apiToggleMaintenanceModeEndpoint.cjs");
|
|
5
5
|
const require_testSiteKey = require("./testSiteKey.cjs");
|
|
6
|
-
const require_maintenanceModeResponses = require("./captcha/maintenanceModeResponses.cjs");
|
|
7
6
|
const require_requestBodySummary = require("./requestBodySummary.cjs");
|
|
7
|
+
const require_maintenanceModeResponses = require("./captcha/maintenanceModeResponses.cjs");
|
|
8
8
|
const require_forwardVerify = require("./forwardVerify.cjs");
|
|
9
9
|
let _prosopo_common = require("@prosopo/common");
|
|
10
10
|
let _prosopo_types = require("@prosopo/types");
|
|
11
|
-
let _prosopo_util_crypto = require("@prosopo/util-crypto");
|
|
12
11
|
let _prosopo_api_express_router = require("@prosopo/api-express-router");
|
|
12
|
+
let _prosopo_util_crypto = require("@prosopo/util-crypto");
|
|
13
13
|
let express = require("express");
|
|
14
14
|
express = require_runtime.__toESM(express, 1);
|
|
15
15
|
let _prosopo_api = require("@prosopo/api");
|
|
@@ -28,7 +28,9 @@ var deriveVerifySource = (body) => {
|
|
|
28
28
|
var VERIFY_PATH_TYPE = {
|
|
29
29
|
[_prosopo_types.ClientApiPaths.VerifyImageCaptchaSolutionDapp]: _prosopo_types.CaptchaType.image,
|
|
30
30
|
[_prosopo_types.ClientApiPaths.VerifyPowCaptchaSolution]: _prosopo_types.CaptchaType.pow,
|
|
31
|
-
[_prosopo_types.ClientApiPaths.VerifyPuzzleCaptchaSolution]: _prosopo_types.CaptchaType.puzzle
|
|
31
|
+
[_prosopo_types.ClientApiPaths.VerifyPuzzleCaptchaSolution]: _prosopo_types.CaptchaType.puzzle,
|
|
32
|
+
[_prosopo_types.ClientApiPaths.VerifyAudioCaptchaSolution]: _prosopo_types.CaptchaType.audio,
|
|
33
|
+
[_prosopo_types.ClientApiPaths.VerifyIconOrderCaptchaSolution]: _prosopo_types.CaptchaType.iconOrder
|
|
32
34
|
};
|
|
33
35
|
var decodeTokenOr400 = (token, i18n, logger, next) => {
|
|
34
36
|
try {
|
|
@@ -61,6 +63,105 @@ var dappSignatureError = (signature, message, pair, req) => {
|
|
|
61
63
|
}
|
|
62
64
|
};
|
|
63
65
|
/**
|
|
66
|
+
* Verifies a dapp's token for an interactive captcha type as approved or not.
|
|
67
|
+
* The body carries the token, the dapp's signature over it, and optional
|
|
68
|
+
* `ip`, `email` and `clientSessionId`.
|
|
69
|
+
*/
|
|
70
|
+
var interactiveVerifyHandler = ({ env, userAccessRulesStorage, path, label, handlerName, manager }) => async (req, res, next) => {
|
|
71
|
+
if (require_apiToggleMaintenanceModeEndpoint.getMaintenanceMode()) {
|
|
72
|
+
req.logger.info(() => ({ msg: `Maintenance mode active - returning verified for ${label} captcha verification` }));
|
|
73
|
+
const verificationResponse = require_maintenanceModeResponses.buildMaintenanceVerificationResponse(req.i18n.t);
|
|
74
|
+
return res.json(verificationResponse);
|
|
75
|
+
}
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = _prosopo_types.ServerPuzzleCaptchaVerifyRequestBody.parse(req.body);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
return next(new _prosopo_common.ProsopoApiError("CAPTCHA.PARSE_ERROR", {
|
|
81
|
+
context: {
|
|
82
|
+
code: 400,
|
|
83
|
+
error: err,
|
|
84
|
+
body: require_requestBodySummary.summariseRequestBody(req)
|
|
85
|
+
},
|
|
86
|
+
i18n: req.i18n,
|
|
87
|
+
logger: req.logger
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const { token, dappSignature, ip, email, clientSessionId } = parsed;
|
|
92
|
+
const decoded = decodeTokenOr400(token, req.i18n, req.logger, next);
|
|
93
|
+
if (decoded === null) return;
|
|
94
|
+
const { dapp, user, timestamp, challenge, providerUrl } = decoded;
|
|
95
|
+
const testVerdict = require_testSiteKey.resolveTestSiteKeyVerdict(dapp, req.logger);
|
|
96
|
+
if (testVerdict !== null) {
|
|
97
|
+
const verificationResponse = {
|
|
98
|
+
status: "ok",
|
|
99
|
+
verified: testVerdict
|
|
100
|
+
};
|
|
101
|
+
return res.json(verificationResponse);
|
|
102
|
+
}
|
|
103
|
+
const forwarded = await require_forwardVerify.forwardVerifyIfNotIssuer({
|
|
104
|
+
env,
|
|
105
|
+
logger: req.logger,
|
|
106
|
+
path,
|
|
107
|
+
providerUrl,
|
|
108
|
+
dapp,
|
|
109
|
+
user,
|
|
110
|
+
body: parsed,
|
|
111
|
+
alreadyForwarded: req.headers[_prosopo_api.VERIFY_FORWARDED_HEADER] !== void 0
|
|
112
|
+
});
|
|
113
|
+
if (forwarded) return res.json(forwarded);
|
|
114
|
+
const tasks = new require_tasks.Tasks(env, req.logger);
|
|
115
|
+
(0, _prosopo_util_crypto.validateAddress)(dapp, false, 42);
|
|
116
|
+
(0, _prosopo_util_crypto.validateAddress)(user, false, 42);
|
|
117
|
+
const clientRecord = await tasks.db.getClientRecord(dapp);
|
|
118
|
+
if (!clientRecord) return next(new _prosopo_common.ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
|
|
119
|
+
context: {
|
|
120
|
+
code: 400,
|
|
121
|
+
siteKey: dapp
|
|
122
|
+
},
|
|
123
|
+
i18n: req.i18n,
|
|
124
|
+
logger: req.logger
|
|
125
|
+
}));
|
|
126
|
+
if (!challenge) {
|
|
127
|
+
const unverifiedResponse = {
|
|
128
|
+
status: req.i18n.t("API.USER_NOT_VERIFIED"),
|
|
129
|
+
[_prosopo_types.ApiParams.verified]: false
|
|
130
|
+
};
|
|
131
|
+
return res.json(unverifiedResponse);
|
|
132
|
+
}
|
|
133
|
+
const dappPair = env.keyring.addFromAddress(dapp);
|
|
134
|
+
const signatureError = dappSignatureError(dappSignature, timestamp.toString(), dappPair, req);
|
|
135
|
+
if (signatureError) return next(signatureError);
|
|
136
|
+
if (require_apiToggleMaintenanceModeEndpoint.isSiteKeyInMaintenanceMode(dapp)) {
|
|
137
|
+
req.logger.info(() => ({
|
|
138
|
+
msg: "Site key in maintenance mode - returning verified",
|
|
139
|
+
data: { siteKey: dapp }
|
|
140
|
+
}));
|
|
141
|
+
const maintenanceResponse = require_maintenanceModeResponses.buildMaintenanceVerificationResponse(req.i18n.t);
|
|
142
|
+
return res.json(maintenanceResponse);
|
|
143
|
+
}
|
|
144
|
+
const captchaManager = manager(tasks);
|
|
145
|
+
const { verified, score, sessionId } = await captchaManager.serverVerifyInteractiveCaptchaSolution(dapp, challenge, clientRecord.settings.verifiedTimeout, env, ip, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata, clientSessionId);
|
|
146
|
+
const verificationResponse = captchaManager.getVerificationResponse(verified, clientRecord, req.i18n.t, score, void 0, sessionId);
|
|
147
|
+
return res.json(verificationResponse);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
req.logger.error(() => ({
|
|
150
|
+
msg: `Error in ${handlerName}`,
|
|
151
|
+
err,
|
|
152
|
+
data: { body: require_requestBodySummary.summariseRequestBody(req) }
|
|
153
|
+
}));
|
|
154
|
+
return next(new _prosopo_common.ProsopoApiError("API.BAD_REQUEST", {
|
|
155
|
+
context: {
|
|
156
|
+
code: 500,
|
|
157
|
+
error: err
|
|
158
|
+
},
|
|
159
|
+
i18n: req.i18n,
|
|
160
|
+
logger: req.logger
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
64
165
|
* Returns a router connected to the database which can interact with the Proposo protocol
|
|
65
166
|
*
|
|
66
167
|
* @return {Router} - A middleware router that can interact with the Prosopo protocol
|
|
@@ -166,6 +267,14 @@ function prosopoVerifyRouter(env) {
|
|
|
166
267
|
const keyPair = env.keyring.addFromAddress(dapp);
|
|
167
268
|
const signatureError = dappSignatureError(dappSignature, timestamp.toString(), keyPair, req);
|
|
168
269
|
if (signatureError) return next(signatureError);
|
|
270
|
+
if (require_apiToggleMaintenanceModeEndpoint.isSiteKeyInMaintenanceMode(dapp)) {
|
|
271
|
+
req.logger.info(() => ({
|
|
272
|
+
msg: "Site key in maintenance mode - returning verified",
|
|
273
|
+
data: { siteKey: dapp }
|
|
274
|
+
}));
|
|
275
|
+
const maintenanceResponse = require_maintenanceModeResponses.buildMaintenanceVerificationResponse(req.i18n.t);
|
|
276
|
+
return res.json(maintenanceResponse);
|
|
277
|
+
}
|
|
169
278
|
const response = await tasks.imgCaptchaManager.verifyImageCaptchaSolution(user, dapp, commitmentId, env, maxVerifiedTime, ip, clientRecord.settings.disallowWebView, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata, clientSessionId);
|
|
170
279
|
req.logger.debug(() => ({ data: { response } }));
|
|
171
280
|
const verificationResponse = tasks.imgCaptchaManager.getVerificationResponse(response[_prosopo_types.ApiParams.verified], clientRecord, req.i18n.t, response[_prosopo_types.ApiParams.score], response[_prosopo_types.ApiParams.commitmentId], response[_prosopo_types.ApiParams.status], response[_prosopo_types.ApiParams.sessionId]);
|
|
@@ -260,6 +369,14 @@ function prosopoVerifyRouter(env) {
|
|
|
260
369
|
const dappPair = env.keyring.addFromAddress(dapp);
|
|
261
370
|
const signatureError = dappSignatureError(dappSignature, timestamp.toString(), dappPair, req);
|
|
262
371
|
if (signatureError) return next(signatureError);
|
|
372
|
+
if (require_apiToggleMaintenanceModeEndpoint.isSiteKeyInMaintenanceMode(dapp)) {
|
|
373
|
+
req.logger.info(() => ({
|
|
374
|
+
msg: "Site key in maintenance mode - returning verified",
|
|
375
|
+
data: { siteKey: dapp }
|
|
376
|
+
}));
|
|
377
|
+
const maintenanceResponse = require_maintenanceModeResponses.buildMaintenanceVerificationResponse(req.i18n.t);
|
|
378
|
+
return res.json(maintenanceResponse);
|
|
379
|
+
}
|
|
263
380
|
const { verified, score, reason, sessionId } = await tasks.powCaptchaManager.serverVerifyPowCaptchaSolution(dapp, challenge, clientRecord.settings.verifiedTimeout, env, ip, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata, clientSessionId);
|
|
264
381
|
const verificationResponse = tasks.powCaptchaManager.getVerificationResponse(verified, clientRecord, req.i18n.t, score, reason, sessionId);
|
|
265
382
|
return res.json(verificationResponse);
|
|
@@ -279,98 +396,30 @@ function prosopoVerifyRouter(env) {
|
|
|
279
396
|
}));
|
|
280
397
|
}
|
|
281
398
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
logger: req.logger
|
|
307
|
-
}));
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
const { token, dappSignature, ip, email, clientSessionId } = parsed;
|
|
311
|
-
const decoded = decodeTokenOr400(token, req.i18n, req.logger, next);
|
|
312
|
-
if (decoded === null) return;
|
|
313
|
-
const { dapp, user, timestamp, challenge, providerUrl } = decoded;
|
|
314
|
-
const testVerdict = require_testSiteKey.resolveTestSiteKeyVerdict(dapp, req.logger);
|
|
315
|
-
if (testVerdict !== null) {
|
|
316
|
-
const verificationResponse = {
|
|
317
|
-
status: "ok",
|
|
318
|
-
verified: testVerdict
|
|
319
|
-
};
|
|
320
|
-
return res.json(verificationResponse);
|
|
321
|
-
}
|
|
322
|
-
const forwarded = await require_forwardVerify.forwardVerifyIfNotIssuer({
|
|
323
|
-
env,
|
|
324
|
-
logger: req.logger,
|
|
325
|
-
path: _prosopo_types.ClientApiPaths.VerifyPuzzleCaptchaSolution,
|
|
326
|
-
providerUrl,
|
|
327
|
-
dapp,
|
|
328
|
-
user,
|
|
329
|
-
body: parsed,
|
|
330
|
-
alreadyForwarded: req.headers[_prosopo_api.VERIFY_FORWARDED_HEADER] !== void 0
|
|
331
|
-
});
|
|
332
|
-
if (forwarded) return res.json(forwarded);
|
|
333
|
-
const tasks = new require_tasks.Tasks(env, req.logger);
|
|
334
|
-
(0, _prosopo_util_crypto.validateAddress)(dapp, false, 42);
|
|
335
|
-
(0, _prosopo_util_crypto.validateAddress)(user, false, 42);
|
|
336
|
-
const clientRecord = await tasks.db.getClientRecord(dapp);
|
|
337
|
-
if (!clientRecord) return next(new _prosopo_common.ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
|
|
338
|
-
context: {
|
|
339
|
-
code: 400,
|
|
340
|
-
siteKey: dapp
|
|
341
|
-
},
|
|
342
|
-
i18n: req.i18n,
|
|
343
|
-
logger: req.logger
|
|
344
|
-
}));
|
|
345
|
-
if (!challenge) {
|
|
346
|
-
const unverifiedResponse = {
|
|
347
|
-
status: req.i18n.t("API.USER_NOT_VERIFIED"),
|
|
348
|
-
[_prosopo_types.ApiParams.verified]: false
|
|
349
|
-
};
|
|
350
|
-
return res.json(unverifiedResponse);
|
|
351
|
-
}
|
|
352
|
-
const dappPair = env.keyring.addFromAddress(dapp);
|
|
353
|
-
const signatureError = dappSignatureError(dappSignature, timestamp.toString(), dappPair, req);
|
|
354
|
-
if (signatureError) return next(signatureError);
|
|
355
|
-
const { verified, score, sessionId } = await tasks.puzzleCaptchaManager.serverVerifyPuzzleCaptchaSolution(dapp, challenge, clientRecord.settings.verifiedTimeout, env, ip, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata, clientSessionId);
|
|
356
|
-
const verificationResponse = tasks.puzzleCaptchaManager.getVerificationResponse(verified, clientRecord, req.i18n.t, score, void 0, sessionId);
|
|
357
|
-
return res.json(verificationResponse);
|
|
358
|
-
} catch (err) {
|
|
359
|
-
req.logger.error(() => ({
|
|
360
|
-
msg: "Error in verifyPuzzleCaptchaSolution",
|
|
361
|
-
err,
|
|
362
|
-
data: { body: require_requestBodySummary.summariseRequestBody(req) }
|
|
363
|
-
}));
|
|
364
|
-
return next(new _prosopo_common.ProsopoApiError("API.BAD_REQUEST", {
|
|
365
|
-
context: {
|
|
366
|
-
code: 500,
|
|
367
|
-
error: err
|
|
368
|
-
},
|
|
369
|
-
i18n: req.i18n,
|
|
370
|
-
logger: req.logger
|
|
371
|
-
}));
|
|
372
|
-
}
|
|
373
|
-
});
|
|
399
|
+
router.post(_prosopo_types.ClientApiPaths.VerifyPuzzleCaptchaSolution, interactiveVerifyHandler({
|
|
400
|
+
env,
|
|
401
|
+
userAccessRulesStorage,
|
|
402
|
+
path: _prosopo_types.ClientApiPaths.VerifyPuzzleCaptchaSolution,
|
|
403
|
+
label: "puzzle",
|
|
404
|
+
handlerName: "verifyPuzzleCaptchaSolution",
|
|
405
|
+
manager: (tasks) => tasks.puzzleCaptchaManager
|
|
406
|
+
}));
|
|
407
|
+
router.post(_prosopo_types.ClientApiPaths.VerifyAudioCaptchaSolution, interactiveVerifyHandler({
|
|
408
|
+
env,
|
|
409
|
+
userAccessRulesStorage,
|
|
410
|
+
path: _prosopo_types.ClientApiPaths.VerifyAudioCaptchaSolution,
|
|
411
|
+
label: "audio",
|
|
412
|
+
handlerName: "verifyAudioCaptchaSolution",
|
|
413
|
+
manager: (tasks) => tasks.audioCaptchaManager
|
|
414
|
+
}));
|
|
415
|
+
router.post(_prosopo_types.ClientApiPaths.VerifyIconOrderCaptchaSolution, interactiveVerifyHandler({
|
|
416
|
+
env,
|
|
417
|
+
userAccessRulesStorage,
|
|
418
|
+
path: _prosopo_types.ClientApiPaths.VerifyIconOrderCaptchaSolution,
|
|
419
|
+
label: "icon-order",
|
|
420
|
+
handlerName: "verifyIconOrderCaptchaSolution",
|
|
421
|
+
manager: (tasks) => tasks.iconOrderCaptchaManager
|
|
422
|
+
}));
|
|
374
423
|
/**
|
|
375
424
|
* Verify a Web Bot Auth authenticated session token. Enforces IP binding:
|
|
376
425
|
* the operator MUST forward `ip` in the request body, and it must equal
|
|
@@ -434,6 +483,14 @@ function prosopoVerifyRouter(env) {
|
|
|
434
483
|
const keyPair = env.keyring.addFromAddress(dapp);
|
|
435
484
|
const signatureError = dappSignatureError(dappSignature, timestamp.toString(), keyPair, req);
|
|
436
485
|
if (signatureError) return next(signatureError);
|
|
486
|
+
if (require_apiToggleMaintenanceModeEndpoint.isSiteKeyInMaintenanceMode(dapp)) {
|
|
487
|
+
req.logger.info(() => ({
|
|
488
|
+
msg: "Site key in maintenance mode - returning verified",
|
|
489
|
+
data: { siteKey: dapp }
|
|
490
|
+
}));
|
|
491
|
+
const maintenanceResponse = require_maintenanceModeResponses.buildMaintenanceVerificationResponse(req.i18n.t);
|
|
492
|
+
return res.json(maintenanceResponse);
|
|
493
|
+
}
|
|
437
494
|
if (!sessionId) return res.json({
|
|
438
495
|
status: "API.USER_NOT_VERIFIED_NO_SOLUTION",
|
|
439
496
|
verified: false
|
|
@@ -4,6 +4,11 @@ let ip_address = require("ip-address");
|
|
|
4
4
|
//#region src/compositeIpAddress.ts
|
|
5
5
|
var V6_SHIFT = 64n;
|
|
6
6
|
var v6_LOWER_MASK = (1n << V6_SHIFT) - 1n;
|
|
7
|
+
/**
|
|
8
|
+
* The part of a v4 address treated as the host rather than the network, for
|
|
9
|
+
* the purposes of `isSameIpOrigin`. 8 bits — a /24.
|
|
10
|
+
*/
|
|
11
|
+
var V4_HOST_BITS = 8n;
|
|
7
12
|
var getCompositeIpAddress = (ip) => {
|
|
8
13
|
let ipAddress;
|
|
9
14
|
try {
|
|
@@ -60,10 +65,19 @@ var isUnknownIp = (ip) => ip.type === _prosopo_types.IpAddressType.v4 && readPar
|
|
|
60
65
|
/**
|
|
61
66
|
* Do two observations of a client come from the same place on the network?
|
|
62
67
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
68
|
+
* Both families are compared on the network part and neither on the host part.
|
|
69
|
+
*
|
|
70
|
+
* v6 is the /64 prefix: the interface identifier in the low 64 bits is designed
|
|
71
|
+
* to rotate (RFC 8981 privacy extensions), often several times a day on one
|
|
72
|
+
* unchanged connection, so comparing it would call an ordinary phone a
|
|
73
|
+
* different host.
|
|
74
|
+
*
|
|
75
|
+
* v4 is the /24. A carrier NAT or mobile pool reassigns the low octet mid
|
|
76
|
+
* session — an EE subscriber was observed moving one address in four seconds —
|
|
77
|
+
* so comparing the whole address called every rotating mobile and CGNAT client
|
|
78
|
+
* a different host, which is the opposite of the leniency this check is for.
|
|
79
|
+
* The /24 still separates an unrelated network, which is the case worth
|
|
80
|
+
* catching: a challenge handed to a second host to farm the work out.
|
|
67
81
|
*
|
|
68
82
|
* A value we do not actually have counts as the same — one that will not
|
|
69
83
|
* parse, or the all-zero v4 `getCompositeIpAddress` returns when handed an
|
|
@@ -73,13 +87,13 @@ var isUnknownIp = (ip) => ip.type === _prosopo_types.IpAddressType.v4 && readPar
|
|
|
73
87
|
var isSameIpOrigin = (a, b) => {
|
|
74
88
|
if (isUnknownIp(a) || isUnknownIp(b)) return true;
|
|
75
89
|
if (a.type !== b.type) return false;
|
|
76
|
-
const
|
|
90
|
+
const sameNetwork = (left, right, hostBits) => {
|
|
77
91
|
const leftPart = readPart(left);
|
|
78
92
|
const rightPart = readPart(right);
|
|
79
93
|
if (leftPart === void 0 || rightPart === void 0) return true;
|
|
80
|
-
return leftPart === rightPart;
|
|
94
|
+
return leftPart >> hostBits === rightPart >> hostBits;
|
|
81
95
|
};
|
|
82
|
-
return a.type === _prosopo_types.IpAddressType.v6 ?
|
|
96
|
+
return a.type === _prosopo_types.IpAddressType.v6 ? sameNetwork(a.upper, b.upper, 0n) : sameNetwork(a.lower, b.lower, V4_HOST_BITS);
|
|
83
97
|
};
|
|
84
98
|
var never = () => {
|
|
85
99
|
throw new Error("Unhandled type");
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_compositeIpAddress = require("./compositeIpAddress.cjs");
|
|
3
|
-
const require_blacklistRequestInspector = require("./api/blacklistRequestInspector.cjs");
|
|
4
3
|
const require_ipComparison = require("./services/ipComparison.cjs");
|
|
5
4
|
const require_util = require("./util.cjs");
|
|
5
|
+
const require_blacklistRequestInspector = require("./api/blacklistRequestInspector.cjs");
|
|
6
6
|
const require_tasks = require("./tasks/tasks.cjs");
|
|
7
7
|
const require_updateSpamEmailDomains = require("./tasks/spam/updateSpamEmailDomains.cjs");
|
|
8
8
|
const require_block = require("./api/block.cjs");
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
let _prosopo_audio_assets = require("@prosopo/audio-assets");
|
|
2
|
+
var settingsKey = (settings) => [
|
|
3
|
+
settings.digitCount,
|
|
4
|
+
settings.noiseSnrDb,
|
|
5
|
+
settings.babbleGain,
|
|
6
|
+
settings.babbleVoices,
|
|
7
|
+
settings.reverbMix,
|
|
8
|
+
settings.gapMs
|
|
9
|
+
].join(":");
|
|
10
|
+
var createAudioChallengeBuffer = (options = {}) => {
|
|
11
|
+
const capacity = options.capacity ?? 8;
|
|
12
|
+
const refillIntervalMs = options.refillIntervalMs ?? 500;
|
|
13
|
+
const refillBatch = options.refillBatch ?? 2;
|
|
14
|
+
const maxVariants = options.maxVariants ?? 8;
|
|
15
|
+
const variants = /* @__PURE__ */ new Map();
|
|
16
|
+
let starved = 0;
|
|
17
|
+
const touch = (key, settings) => {
|
|
18
|
+
const existing = variants.get(key);
|
|
19
|
+
if (existing) {
|
|
20
|
+
variants.delete(key);
|
|
21
|
+
variants.set(key, existing);
|
|
22
|
+
return existing;
|
|
23
|
+
}
|
|
24
|
+
const created = {
|
|
25
|
+
settings,
|
|
26
|
+
ready: []
|
|
27
|
+
};
|
|
28
|
+
variants.set(key, created);
|
|
29
|
+
while (variants.size > maxVariants) {
|
|
30
|
+
const oldest = variants.keys().next().value;
|
|
31
|
+
if (oldest === void 0) break;
|
|
32
|
+
variants.delete(oldest);
|
|
33
|
+
}
|
|
34
|
+
return created;
|
|
35
|
+
};
|
|
36
|
+
const topUp = (limit) => {
|
|
37
|
+
for (const variant of variants.values()) for (let i = 0; i < limit && variant.ready.length < capacity; i++) variant.ready.push((0, _prosopo_audio_assets.renderAudioChallenge)(variant.settings));
|
|
38
|
+
};
|
|
39
|
+
const prime = options.primeSettings ?? _prosopo_audio_assets.DEFAULT_RENDER_SETTINGS;
|
|
40
|
+
touch(settingsKey(prime), prime);
|
|
41
|
+
topUp(capacity);
|
|
42
|
+
const timer = setInterval(() => topUp(refillBatch), refillIntervalMs);
|
|
43
|
+
timer.unref?.();
|
|
44
|
+
return {
|
|
45
|
+
take(settings) {
|
|
46
|
+
const challenge = touch(settingsKey(settings), settings).ready.pop();
|
|
47
|
+
if (!challenge) {
|
|
48
|
+
starved++;
|
|
49
|
+
return (0, _prosopo_audio_assets.renderAudioChallenge)(settings);
|
|
50
|
+
}
|
|
51
|
+
return challenge;
|
|
52
|
+
},
|
|
53
|
+
depth: () => {
|
|
54
|
+
let total = 0;
|
|
55
|
+
for (const variant of variants.values()) total += variant.ready.length;
|
|
56
|
+
return total;
|
|
57
|
+
},
|
|
58
|
+
starvations: () => starved,
|
|
59
|
+
stop: () => clearInterval(timer)
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
var globalBuffer = null;
|
|
63
|
+
var initAudioChallengeBuffer = (options = {}) => {
|
|
64
|
+
globalBuffer?.stop();
|
|
65
|
+
globalBuffer = createAudioChallengeBuffer(options);
|
|
66
|
+
return globalBuffer;
|
|
67
|
+
};
|
|
68
|
+
var getAudioChallengeBuffer = () => globalBuffer;
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.createAudioChallengeBuffer = createAudioChallengeBuffer;
|
|
71
|
+
exports.getAudioChallengeBuffer = getAudioChallengeBuffer;
|
|
72
|
+
exports.initAudioChallengeBuffer = initAudioChallengeBuffer;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const require_audioBuffer = require("./audioBuffer.cjs");
|
|
2
|
+
let _prosopo_audio_assets = require("@prosopo/audio-assets");
|
|
3
|
+
//#region src/tasks/audio/audioRenderer.ts
|
|
4
|
+
/** Layers partial overrides onto the asset defaults; later sources win. */
|
|
5
|
+
var resolveAudioRenderSettings = (...overrides) => {
|
|
6
|
+
let resolved = { ..._prosopo_audio_assets.DEFAULT_RENDER_SETTINGS };
|
|
7
|
+
for (const override of overrides) resolved = {
|
|
8
|
+
digitCount: override?.digitCount ?? resolved.digitCount,
|
|
9
|
+
noiseSnrDb: override?.noiseSnrDb ?? resolved.noiseSnrDb,
|
|
10
|
+
babbleGain: override?.babbleGain ?? resolved.babbleGain,
|
|
11
|
+
babbleVoices: override?.babbleVoices ?? resolved.babbleVoices,
|
|
12
|
+
reverbMix: override?.reverbMix ?? resolved.reverbMix,
|
|
13
|
+
gapMs: override?.gapMs ?? resolved.gapMs
|
|
14
|
+
};
|
|
15
|
+
return resolved;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Takes one challenge from the process-wide buffer, created on first use so a
|
|
19
|
+
* provider that never serves audio pays nothing for it.
|
|
20
|
+
*/
|
|
21
|
+
var renderAudioClip = (settings) => {
|
|
22
|
+
const challenge = (require_audioBuffer.getAudioChallengeBuffer() ?? require_audioBuffer.initAudioChallengeBuffer()).take(settings);
|
|
23
|
+
return {
|
|
24
|
+
clip: (0, _prosopo_audio_assets.toDataUri)(challenge.wav),
|
|
25
|
+
characterCount: challenge.answer.length,
|
|
26
|
+
answer: challenge.answer,
|
|
27
|
+
durationMs: challenge.durationMs
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.renderAudioClip = renderAudioClip;
|
|
32
|
+
exports.resolveAudioRenderSettings = resolveAudioRenderSettings;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
let _prosopo_types = require("@prosopo/types");
|
|
2
|
+
//#region src/tasks/audioAlternative.ts
|
|
3
|
+
var AUDIO_ALTERNATIVE_SESSION_TYPES = /* @__PURE__ */ new Set([
|
|
4
|
+
_prosopo_types.CaptchaType.image,
|
|
5
|
+
_prosopo_types.CaptchaType.puzzle,
|
|
6
|
+
_prosopo_types.CaptchaType.iconOrder
|
|
7
|
+
]);
|
|
8
|
+
/** Whether a session of this type is a visual challenge that can offer audio. */
|
|
9
|
+
var isAudioAlternativeSessionType = (captchaType) => captchaType !== void 0 && AUDIO_ALTERNATIVE_SESSION_TYPES.has(captchaType);
|
|
10
|
+
/**
|
|
11
|
+
* The site owner has to turn the alternative on, and Prosopo has to have
|
|
12
|
+
* switched on the audio feature flag for the site.
|
|
13
|
+
*/
|
|
14
|
+
var isAudioAlternativeEnabled = (settings) => settings?.audioAccessibilityEnabled === true && (0, _prosopo_types.isCaptchaTypeFeatureEnabled)(_prosopo_types.CaptchaType.audio, settings.captchaTypeFeatureFlags);
|
|
15
|
+
/** Whether a challenge of this type shows "use audio instead". */
|
|
16
|
+
var offersAudioAlternative = (captchaType, audioAlternativeEnabled) => audioAlternativeEnabled && isAudioAlternativeSessionType(captchaType);
|
|
17
|
+
/** Whether an audio challenge may be issued against a session of another type. */
|
|
18
|
+
var isAudioAlternativeAllowed = (requestedCaptchaType, sessionCaptchaType, settings) => requestedCaptchaType === _prosopo_types.CaptchaType.audio && offersAudioAlternative(sessionCaptchaType, isAudioAlternativeEnabled(settings));
|
|
19
|
+
//#endregion
|
|
20
|
+
exports.isAudioAlternativeAllowed = isAudioAlternativeAllowed;
|
|
21
|
+
exports.isAudioAlternativeEnabled = isAudioAlternativeEnabled;
|
|
22
|
+
exports.isAudioAlternativeSessionType = isAudioAlternativeSessionType;
|
|
23
|
+
exports.offersAudioAlternative = offersAudioAlternative;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const require_audioRenderer = require("../audio/audioRenderer.cjs");
|
|
2
|
+
const require_interactiveCaptchaManager = require("../interactiveCaptcha/interactiveCaptchaManager.cjs");
|
|
3
|
+
const require_audioTasksUtils = require("./audioTasksUtils.cjs");
|
|
4
|
+
let _prosopo_types = require("@prosopo/types");
|
|
5
|
+
//#region src/tasks/audioCaptcha/audioTasks.ts
|
|
6
|
+
var AudioCaptchaManager = class extends require_interactiveCaptchaManager.InteractiveCaptchaManager {
|
|
7
|
+
constructor(..._args) {
|
|
8
|
+
super(..._args);
|
|
9
|
+
this.captchaType = _prosopo_types.CaptchaType.audio;
|
|
10
|
+
this.logLabel = "audio";
|
|
11
|
+
}
|
|
12
|
+
getRecordByChallenge(challenge) {
|
|
13
|
+
return this.db.getAudioCaptchaRecordByChallenge(challenge);
|
|
14
|
+
}
|
|
15
|
+
updateRecord(challenge, updates) {
|
|
16
|
+
return this.db.updateAudioCaptchaRecord(challenge, updates);
|
|
17
|
+
}
|
|
18
|
+
updateSubmissionResult(challenge, result, userSignature, coords) {
|
|
19
|
+
return this.db.updateAudioCaptchaRecordResult(challenge, result, false, true, userSignature, coords);
|
|
20
|
+
}
|
|
21
|
+
/** Atomic, so concurrent submissions cannot each be graded. */
|
|
22
|
+
claimSubmission(record) {
|
|
23
|
+
return this.db.claimAudioCaptchaSubmission(record.challenge);
|
|
24
|
+
}
|
|
25
|
+
markRecordChecked(challenge) {
|
|
26
|
+
return this.db.markAudioCaptchaRecordChecked(challenge);
|
|
27
|
+
}
|
|
28
|
+
decisionMachineEventFields(record) {
|
|
29
|
+
return {
|
|
30
|
+
audioEvents: record.audioEvents,
|
|
31
|
+
audioReplays: record.replays
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The renderer picks the digits, so the answer only exists once the clip
|
|
36
|
+
* does; the caller must store `answer` before responding.
|
|
37
|
+
*/
|
|
38
|
+
getAudioCaptchaChallenge(userAccount, dappAccount, settings) {
|
|
39
|
+
return {
|
|
40
|
+
...this.mintChallenge(userAccount, dappAccount),
|
|
41
|
+
...require_audioRenderer.renderAudioClip(settings)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async verifyAudioCaptchaSolution(challenge, providerChallengeSignature, submittedAnswer, replays, audioEvents, timeout, userTimestampSignature, ipAddress, behavioralData, salt, simdReadings, clientMetaData) {
|
|
45
|
+
return this.submitInteractiveCaptchaSolution({
|
|
46
|
+
challenge,
|
|
47
|
+
providerChallengeSignature,
|
|
48
|
+
timeout,
|
|
49
|
+
userTimestampSignature,
|
|
50
|
+
ipAddress,
|
|
51
|
+
behavioralData,
|
|
52
|
+
salt,
|
|
53
|
+
simdReadings,
|
|
54
|
+
clientMetaData,
|
|
55
|
+
isCorrect: (record) => require_audioTasksUtils.validateAudioSolution(submittedAnswer, record.answer),
|
|
56
|
+
persistInteraction: () => this.db.updateAudioCaptchaRecord(challenge, {
|
|
57
|
+
audioEvents,
|
|
58
|
+
replays,
|
|
59
|
+
submittedAnswer: require_audioTasksUtils.normaliseAudioAnswer(submittedAnswer)
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
exports.AudioCaptchaManager = AudioCaptchaManager;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/tasks/audioCaptcha/audioTasksUtils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Keeps only the digits, in order: "1 2 3", "1-2-3" and screen-reader inserted
|
|
4
|
+
* separators all grade the same, and no different digit sequence can pass.
|
|
5
|
+
*/
|
|
6
|
+
var normaliseAudioAnswer = (raw) => raw.replace(/\D/g, "");
|
|
7
|
+
/**
|
|
8
|
+
* Exact match after normalisation. No edit-distance slack: one substitution
|
|
9
|
+
* widens the accepted set far more than it helps a listener, and a wrong
|
|
10
|
+
* answer only costs a fresh challenge.
|
|
11
|
+
*/
|
|
12
|
+
var validateAudioSolution = (submitted, expected) => {
|
|
13
|
+
const normalised = normaliseAudioAnswer(submitted);
|
|
14
|
+
if (normalised.length === 0 || expected.length === 0) return false;
|
|
15
|
+
return normalised === expected;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.normaliseAudioAnswer = normaliseAudioAnswer;
|
|
19
|
+
exports.validateAudioSolution = validateAudioSolution;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_compositeIpAddress = require("../compositeIpAddress.cjs");
|
|
2
2
|
const require_blacklistRequestInspector = require("../api/blacklistRequestInspector.cjs");
|
|
3
|
+
const require_audioAlternative = require("./audioAlternative.cjs");
|
|
3
4
|
const require_bundlePool = require("./detection/bundlePool.cjs");
|
|
4
5
|
const require_decoderPool = require("./detection/decoderPool.cjs");
|
|
5
6
|
const require_checkTrafficFilter = require("./spam/checkTrafficFilter.cjs");
|
|
@@ -225,6 +226,21 @@ var CaptchaManager = class CaptchaManager {
|
|
|
225
226
|
sessionId
|
|
226
227
|
}
|
|
227
228
|
}));
|
|
229
|
+
if (!(requestedCaptchaType === _prosopo_types.CaptchaType.audio ? require_audioAlternative.isAudioAlternativeEnabled(clientSettings.settings) : (0, _prosopo_types.isCaptchaTypeFeatureEnabled)(requestedCaptchaType, clientSettings.settings?.captchaTypeFeatureFlags))) {
|
|
230
|
+
this.logger.warn(() => ({
|
|
231
|
+
msg: "Captcha type is switched off for this site",
|
|
232
|
+
data: {
|
|
233
|
+
account: clientSettings.account,
|
|
234
|
+
requestedCaptchaType,
|
|
235
|
+
sessionId
|
|
236
|
+
}
|
|
237
|
+
}));
|
|
238
|
+
return {
|
|
239
|
+
valid: false,
|
|
240
|
+
reason: _prosopo_types.ResultReason.INCORRECT_CAPTCHA_TYPE,
|
|
241
|
+
type: requestedCaptchaType
|
|
242
|
+
};
|
|
243
|
+
}
|
|
228
244
|
if (sessionId) {
|
|
229
245
|
const cachedBeforeRemove = this.writeQueue ? await this.writeQueue.getCachedSession(sessionId) : null;
|
|
230
246
|
const cachedHash = typeof cachedBeforeRemove?.userSitekeyIpHash === "string" ? cachedBeforeRemove.userSitekeyIpHash : void 0;
|
|
@@ -317,7 +333,7 @@ var CaptchaManager = class CaptchaManager {
|
|
|
317
333
|
type: requestedCaptchaType
|
|
318
334
|
};
|
|
319
335
|
}
|
|
320
|
-
if (sessionRecord.captchaType !== requestedCaptchaType) {
|
|
336
|
+
if (sessionRecord.captchaType !== requestedCaptchaType && !require_audioAlternative.isAudioAlternativeAllowed(requestedCaptchaType, sessionRecord.captchaType, clientSettings.settings)) {
|
|
321
337
|
this.logger.warn(() => ({
|
|
322
338
|
msg: "Session captcha type does not match requested type",
|
|
323
339
|
data: {
|
|
@@ -342,6 +358,17 @@ var CaptchaManager = class CaptchaManager {
|
|
|
342
358
|
ipInfo: sessionRecord.ipInfo
|
|
343
359
|
};
|
|
344
360
|
}
|
|
361
|
+
if (requestedCaptchaType === _prosopo_types.CaptchaType.audio) {
|
|
362
|
+
this.logger.warn(() => ({
|
|
363
|
+
msg: "Sessionless audio captcha request rejected",
|
|
364
|
+
data: { account: clientSettings.account }
|
|
365
|
+
}));
|
|
366
|
+
return {
|
|
367
|
+
valid: false,
|
|
368
|
+
reason: _prosopo_types.ResultReason.INCORRECT_CAPTCHA_TYPE,
|
|
369
|
+
type: requestedCaptchaType
|
|
370
|
+
};
|
|
371
|
+
}
|
|
345
372
|
if (userAccessPolicy?.captchaType !== void 0 && userAccessPolicy.captchaType !== requestedCaptchaType) {
|
|
346
373
|
this.logger.warn(() => ({
|
|
347
374
|
msg: "Invalid captcha type for user access policy (sessionless)",
|