Skip to main content

rustauth_plugins/captcha/verify_handlers/
google_recaptcha.rs

1//! Google reCAPTCHA verification handler.
2
3use 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}