rustauth_plugins/captcha/verify_handlers/
google_recaptcha.rs1use serde::Deserialize;
4
5use super::{service_unavailable, CaptchaVerifyError};
6use crate::captcha::CaptchaOptions;
7
8#[derive(Deserialize)]
9struct SiteVerifyResponse {
10 success: bool,
11 score: Option<f64>,
12}
13
14pub async fn verify(
15 options: &CaptchaOptions,
16 captcha_response: &str,
17 remote_ip: Option<String>,
18) -> Result<bool, CaptchaVerifyError> {
19 let client = options.http_client_ref();
20 let mut form = vec![
21 ("secret", options.secret_key.as_str()),
22 ("response", captcha_response),
23 ];
24 if let Some(remote_ip) = remote_ip.as_deref() {
25 form.push(("remoteip", remote_ip));
26 }
27
28 let response = client
29 .post(options.site_verify_url())
30 .form(&form)
31 .send()
32 .await
33 .map_err(service_unavailable)?;
34 if !response.status().is_success() {
35 return Err(service_unavailable(response.status()));
36 }
37 let data = response
38 .json::<SiteVerifyResponse>()
39 .await
40 .map_err(service_unavailable)?;
41
42 let score_ok = match data.score {
43 Some(score) => score >= options.google_min_score(),
44 None => true,
45 };
46 Ok(data.success && score_ok)
47}