File size: 1,244 Bytes
843f9e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { RECAPTCHA_ACTION, RECAPTCHA_MIN_SCORE, RECAPTCHA_VERIFY_URL } from "./constants.js";

// Verify a reCAPTCHA v3 token with Google. Returns { ok, reason }.
// With no secret configured it passes in development and fails closed in production.
export async function verifyRecaptcha(token, ip, { secret = process.env.RECAPTCHA_SECRET, fetchFn = fetch, production = process.env.NODE_ENV === "production" } = {}) {
  if (!secret) return production ? { ok: false, reason: "not-configured" } : { ok: true, reason: "dev-skip" };
  if (typeof token !== "string" || !token) return { ok: false, reason: "missing-token" };
  try {
    const body = new URLSearchParams({ secret, response: token });
    if (ip) body.set("remoteip", ip);
    const res = await fetchFn(RECAPTCHA_VERIFY_URL, { method: "POST", body });
    const data = await res.json();
    if (!data.success) return { ok: false, reason: "rejected" };
    if (data.action && data.action !== RECAPTCHA_ACTION) return { ok: false, reason: "wrong-action" };
    if (typeof data.score === "number" && data.score < RECAPTCHA_MIN_SCORE) return { ok: false, reason: "low-score" };
    return { ok: true, reason: "verified" };
  } catch {
    return { ok: false, reason: "unreachable" };
  }
}