UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

79 lines (78 loc) 3.43 kB
import { wildcardMatch } from "../../utils/wildcard.mjs"; import { PACKAGE_VERSION } from "../../version.mjs"; import { middlewareResponse } from "../../utils/middleware-response.mjs"; import { Providers, defaultEndpoints, siteVerifyMap } from "./constants.mjs"; import { EXTERNAL_ERROR_CODES, INTERNAL_ERROR_CODES } from "./error-codes.mjs"; import { captchaFox } from "./verify-handlers/captchafox.mjs"; import { cloudflareTurnstile } from "./verify-handlers/cloudflare-turnstile.mjs"; import { googleRecaptcha } from "./verify-handlers/google-recaptcha.mjs"; import { hCaptcha } from "./verify-handlers/h-captcha.mjs"; import { getIP } from "@better-auth/core/utils/ip"; //#region src/plugins/captcha/index.ts const normalizeEndpointPath = (pathname, basePath) => { let normalizedPathname = (pathname.startsWith(basePath) ? pathname.slice(basePath.length) : pathname).replace(/\/{2,}/g, "/"); if (!normalizedPathname.startsWith("/")) normalizedPathname = `/${normalizedPathname}`; if (normalizedPathname.length > 1 && normalizedPathname.endsWith("/")) normalizedPathname = normalizedPathname.slice(0, -1); return normalizedPathname; }; const captcha = (options) => ({ id: "captcha", version: PACKAGE_VERSION, $ERROR_CODES: EXTERNAL_ERROR_CODES, onRequest: async (request, ctx) => { try { const endpoints = options.endpoints?.length ? options.endpoints : defaultEndpoints; const url = new URL(request.url); const basePath = ctx.options.basePath ?? "/api/auth"; const pathname = normalizeEndpointPath(url.pathname, basePath); if (!endpoints.some((endpoint) => endpoint.includes("*") ? wildcardMatch(endpoint)(pathname) : endpoint === pathname)) return; if (!options.secretKey) throw new Error(INTERNAL_ERROR_CODES.MISSING_SECRET_KEY.message); const captchaResponse = request.headers.get("x-captcha-response"); const remoteUserIP = getIP(request, ctx.options) ?? void 0; if (!captchaResponse) return middlewareResponse({ message: EXTERNAL_ERROR_CODES.MISSING_RESPONSE.message, code: EXTERNAL_ERROR_CODES.MISSING_RESPONSE.code, status: 400 }); const handlerParams = { siteVerifyURL: options.siteVerifyURLOverride || siteVerifyMap[options.provider], captchaResponse, secretKey: options.secretKey, remoteIP: remoteUserIP }; if (options.provider === Providers.CLOUDFLARE_TURNSTILE) return await cloudflareTurnstile({ ...handlerParams, expectedAction: options.expectedAction, allowedHostnames: options.allowedHostnames }); if (options.provider === Providers.GOOGLE_RECAPTCHA) return await googleRecaptcha({ ...handlerParams, minScore: options.minScore, expectedAction: options.expectedAction, allowedHostnames: options.allowedHostnames }); if (options.provider === Providers.HCAPTCHA) return await hCaptcha({ ...handlerParams, siteKey: options.siteKey }); if (options.provider === Providers.CAPTCHAFOX) return await captchaFox({ ...handlerParams, siteKey: options.siteKey }); } catch (_error) { const errorMessage = _error instanceof Error ? _error.message : void 0; ctx.logger.error(errorMessage ?? "Unknown error", { endpoint: request.url, message: _error }); return middlewareResponse({ message: EXTERNAL_ERROR_CODES.UNKNOWN_ERROR.message, code: EXTERNAL_ERROR_CODES.UNKNOWN_ERROR.code, status: 500 }); } }, options }); //#endregion export { captcha };