feat: Web Bot Auth verifier + authenticated frictionless flow - #3145
feat: Web Bot Auth verifier + authenticated frictionless flow#3145forgetso wants to merge 5 commits into
Conversation
New package @prosopo/web-bot-auth: RFC 9421 HTTP Message Signatures verifier using @noble/curves/ed25519 (no Cloudflare dep). Handles both bare-string (OpenAI) and dictionary (Google) Signature-Agent header forms. 17 unit tests including full Ed25519 round-trip against golden vectors and replay defence. Frictionless flow gains an authenticated fast-path — any non-deferToVerify Allow rule matching the userScope (webBotAuthAgent, ip_cidr, ja4, ua, asn, country) mints an `authenticated` session, skipping decrypt/detect/DM. Web Bot Auth is one of many qualifiers, not the only one. New endpoint POST /v1/prosopo/provider/client/authenticated/verify enforces IP binding: the operator must forward the client IP and it must equal the session's captured IP. serverChecked flow gives single-use. ipMatchesSession extracted to a pure function with 13 unit tests. Schema: - CaptchaType.authenticated added - AccessPolicyType.Allow added - Session record gains `agent: boolean` and `webBotAuthAgent: string` - user-access-policy schema gains webBotAuthAgent scope field (rule.ts, ruleRecord.ts, ruleInput/userScopeInput.ts with URL normalisation, Mongoose + Redis TAG index) - ClientSettings gains `allowAgents?: boolean` (opt-in gate) - GetFrictionlessCaptchaResponse carries `agent` on authenticated responses Widget: - AuthenticatedBadge component: on mount encodes ProcaptchaToken with sessionId as commitmentId, fires events.onHuman. Renders compact "Verified agent: chatgpt.com" or "Trusted request" fallback. - ProcaptchaFrictionless dispatch branch for CaptchaType.authenticated Fixes: - dev/config vite.esm.config.ts: @ts-expect-error on Rolldown polyfillRequire - dev/config configs.test.ts: narrow cast for Vitest custom-provider coverage - provider/util.ts: Mongoose 8 Document._id cast to Types.ObjectId
Upstream Vite's Rollup output types now include polyfillRequire, so the directive is unused and TSC flags it as such. Drop the suppression.
…icated captcha type Extend the Web Bot Auth authenticated fast-path so it participates in the render-time correlation the pow/image/puzzle flows enforce. - `GetFrictionlessCaptchaChallengeRequestBody` gains optional `clientSessionId` — captured at issuance and persisted onto the session record's `clientMetaData`, mirroring how the other captcha types store it. - `verifyAuthenticatedSession` compares via the shared `isClientSessionMismatch` helper — same asymmetric semantics as pow/image/puzzle: verify-side opts in; a real mismatch fails with `API.CLIENT_SESSION_MISMATCH`. - `ProviderApi.submitAuthenticatedCaptchaVerify(token, sig, user, ip?, email?, clientSessionId?)` — dedicated endpoint call so `@prosopo/server` can dispatch on captchaType without a token-shape branch. Email is a wire-parity passthrough (no email correlation on authenticated — Web Bot Auth doesn't carry one). - `verifyProvider` gets a `CaptchaType.authenticated` branch that routes to the new method with ip + email + clientSessionId forwarded. Net effect: a customer's siteverify Lambda passes an authenticated token to `@prosopo/server.isVerified` and it dispatches correctly instead of falling through to the legacy image path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No updates since Nothing is lost — Converting to draft disables auto-merge, so PRs with auto-merge enabled are excluded from this entirely. |
|
No updates since Nothing is lost — Converting to draft disables auto-merge, so PRs with auto-merge enabled are excluded from this entirely. |
|
No updates since Nothing is lost — Converting to draft disables auto-merge, so PRs with auto-merge enabled are excluded from this entirely. |
Summary
@prosopo/web-bot-authpackage: RFC 9421 HTTP Message Signatures verifier built on@noble/curves/ed25519(no Cloudflare dep). Parses Signature-Agent (bare-string + dictionary forms), resolves JWKS at/.well-known/http-message-signatures-directorywith cache-control TTL, verifies Ed25519 over the RFC 9421 signature base./captcha/frictionless, returnscaptchaType: authenticatedwith a session record (serverChecked: false,agent: true,webBotAuthAgent, IP frozen for verify-time binding). Skips decrypt / bot-score / decision machine./client/authenticated/verifyrouter with mandatory IP-binding (API.AUTHENTICATED_IP_REQUIRED/API.AUTHENTICATED_IP_MISMATCH), single-use viaserverChecked,captchaTypegate against replaying other token types.AccessPolicyType.AllowandCaptchaType.authenticatedadded.Session.agent/Session.webBotAuthAgentfields for the "pre-verified pass" analytics filter.ClientSessionId+emailsupport on the authenticated verify path:submitAuthenticatedCaptchaVerifyonProviderApi,CaptchaType.authenticatedbranch in@prosopo/server.verifyProvider,verifyAuthenticatedSessionuses the sharedisClientSessionMismatchhelper for parity with pow/image/puzzle.procaptcha-frictionlessgetsAuthenticatedBadge+ a dispatch branch forCaptchaType.authenticated.Test plan
npm run -w @prosopo/web-bot-auth test— signature-base, structured-fields, Signature-Agent parsing, JWKS resolver, verify happy pathnpm run -w @prosopo/provider build:tsc— provider type-checkscaptchaType: authenticated, session persisted withagent: true/authenticated/verify— missing IP →API.AUTHENTICATED_IP_REQUIRED; wrong IP →API.AUTHENTICATED_IP_MISMATCH; wrong clientSessionId →API.CLIENT_SESSION_MISMATCH; second use →API.USER_ALREADY_VERIFIED@prosopo/server.isVerifiedon an authenticated token dispatches tosubmitAuthenticatedCaptchaVerify(not the legacy image fallback)🤖 Generated with Claude Code