From 39bee607c087c3e5e3c3e3a5b5654c697af343ed Mon Sep 17 00:00:00 2001 From: Ginger Date: Fri, 2 Oct 2026 12:15:16 -0400 Subject: [PATCH] refactor: Remove recaptcha-verify --- Cargo.lock | 18 +------------- Cargo.toml | 1 + src/service/Cargo.toml | 2 -- src/service/client/mod.rs | 40 ++++++++++++++++++++++++++++++- src/service/uiaa/mod.rs | 27 ++++++++++++--------- src/web/Cargo.toml | 4 ---- src/web/pages/account/register.rs | 11 ++++----- 7 files changed, 61 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40dd059f2..449d1cc25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,9 +1162,7 @@ dependencies = [ "openidconnect", "p256", "rand 0.10.3", - "recaptcha-verify", "regex", - "reqwest 0.12.28", "reqwest 0.13.5", "resolvematrix", "ruma", @@ -1202,8 +1200,6 @@ dependencies = [ "lettre", "memory-serve", "openidconnect", - "recaptcha-verify", - "reqwest 0.12.28", "ruma", "serde", "serde_json", @@ -2749,7 +2745,6 @@ dependencies = [ "hyper", "hyper-util", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -4739,17 +4734,6 @@ dependencies = [ "rand_core 0.10.1", ] -[[package]] -name = "recaptcha-verify" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409bf11a93fe93093f3c0254aab67576524f1e0524692615b5b63091dbc88a79" -dependencies = [ - "reqwest 0.12.28", - "serde", - "serde_json", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -4829,7 +4813,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -4879,6 +4862,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", diff --git a/Cargo.toml b/Cargo.toml index 522883d83..bd605174f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -163,6 +163,7 @@ features = [ "hickory-dns", "http2", "stream", + "form", ] [workspace.dependencies.serde] diff --git a/src/service/Cargo.toml b/src/service/Cargo.toml index d647fa976..60a362608 100644 --- a/src/service/Cargo.toml +++ b/src/service/Cargo.toml @@ -117,8 +117,6 @@ url.workspace = true web-push-native.workspace = true webpage.workspace = true webpage.optional = true -recaptcha-verify = { version = "0.2.0", default-features = false } -reqwest_recaptcha = { package = "reqwest", version = "0.12.28", default-features = false, features = ["rustls-tls-native-roots-no-provider"] } # As long as recaptcha-verify's reqwest is outdated yansi.workspace = true lettre.workspace = true resolvematrix.workspace = true diff --git a/src/service/client/mod.rs b/src/service/client/mod.rs index 26ee1ee51..5fe5c79de 100644 --- a/src/service/client/mod.rs +++ b/src/service/client/mod.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; use async_trait::async_trait; -use conduwuit::{Config, Result, Server, err, trace}; +use conduwuit::{Config, Result, Server, err, trace, utils::response::LimitReadExt, warn}; use either::Either; use hickory_resolver::{ TokioResolver, config::ConnectionConfig, net::runtime::TokioRuntimeProvider, @@ -9,6 +9,7 @@ use hickory_resolver::{ use ipaddress::IPAddress; use reqwest::redirect; use resolvematrix::server::{MatrixResolver, MatrixResolverBuilder}; +use serde::Deserialize; use crate::service; @@ -178,6 +179,43 @@ impl Service { .iter() .all(|cidr| !cidr.includes(ip)) } + + #[tracing::instrument(skip_all)] + pub async fn recaptcha_verify(&self, secret: &str, response: &str) -> bool { + #[derive(Deserialize, Default, Debug, Clone)] + struct RecaptchaResponse { + success: bool, + #[serde(rename(deserialize = "error-codes"))] + _error_codes: Option>, + } + + let response = match self + .external_resource + .post("https://www.google.com/recaptcha/api/siteverify") + .form(&[("secret", secret), ("response", response)]) + .send() + .await + { + | Ok(response) => response, + | Err(err) => { + warn!("ReCaptcha request failed: {err}"); + return false; + }, + }; + + let Ok(response) = response.limit_read_text(1024).await else { + warn!("ReCaptcha response was too large??"); + return false; + }; + + match serde_json::from_str::(&response) { + | Ok(response) => response.success, + | Err(err) => { + warn!("ReCaptcha response failed to deserialize: {err}"); + false + }, + } + } } pub fn base(config: &Config) -> Result { diff --git a/src/service/uiaa/mod.rs b/src/service/uiaa/mod.rs index bde12dd67..f78bbe923 100644 --- a/src/service/uiaa/mod.rs +++ b/src/service/uiaa/mod.rs @@ -4,7 +4,7 @@ use std::{ sync::Arc, }; -use conduwuit::{Err, Error, Result, error, utils}; +use conduwuit::{Err, Error, Result, utils}; use futures::StreamExt; use lettre::Address; use ruma::{ @@ -26,7 +26,7 @@ use serde_json::{ use tokio::sync::Mutex; use crate::{ - Dep, config, firstrun, globals, + Dep, client, config, firstrun, globals, oauth::{self, OAuthTicket}, registration_tokens, threepid, users, }; @@ -38,6 +38,7 @@ pub struct Service { struct Services { config: Dep, + client: Dep, firstrun: Dep, globals: Dep, oauth: Dep, @@ -78,6 +79,7 @@ impl crate::Service for Service { Ok(Arc::new(Self { services: Services { config: args.depend::("config"), + client: args.depend::("client"), firstrun: args.depend::("firstrun"), globals: args.depend::("globals"), oauth: args.depend::("oauth"), @@ -586,15 +588,18 @@ impl Service { )); }; - match recaptcha_verify::verify_v3(private_site_key, response, None).await { - | Ok(()) => Ok(AuthType::ReCaptcha), - | Err(e) => { - error!("ReCaptcha verification failed: {e:?}"); - Err(StandardErrorBody::new( - ErrorKind::CaptchaInvalid, - "ReCaptcha verification failed".to_owned(), - )) - }, + if self + .services + .client + .recaptcha_verify(private_site_key, response) + .await + { + Ok(AuthType::ReCaptcha) + } else { + Err(StandardErrorBody::new( + ErrorKind::CaptchaInvalid, + "ReCaptcha verification failed".to_owned(), + )) } }, | AuthData::RegistrationToken(RegistrationToken { token, .. }) => { diff --git a/src/web/Cargo.toml b/src/web/Cargo.toml index f1f8c7810..c40c461e6 100644 --- a/src/web/Cargo.toml +++ b/src/web/Cargo.toml @@ -32,10 +32,6 @@ futures.workspace = true lettre.workspace = true memory-serve = "2.1.0" openidconnect.workspace = true -recaptcha-verify = { default-features = false, version = "0.2.0" } -reqwest_recaptcha = { default-features = false, features = [ - "rustls-tls-native-roots-no-provider", -], package = "reqwest", version = "0.12.28" } # As long as recaptcha-verify's reqwest is outdated ruma.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/src/web/pages/account/register.rs b/src/web/pages/account/register.rs index a17bee043..5abff481e 100644 --- a/src/web/pages/account/register.rs +++ b/src/web/pages/account/register.rs @@ -398,13 +398,10 @@ async fn begin_registration( )); }; - if recaptcha_verify::verify_v3( - recaptcha_private_site_key, - &recaptcha_response, - None, - ) - .await - .is_err() + if !services + .client + .recaptcha_verify(recaptcha_private_site_key, &recaptcha_response) + .await { errors.add( "recaptcha",