diff --git a/api/src/config.js b/api/src/config.js index 19e859f3..866d8400 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -32,6 +32,8 @@ const env = { && parseInt(process.env.PROCESSING_PRIORITY), externalProxy: process.env.API_EXTERNAL_PROXY, + + turnstileSecret: process.env.TURNSTILE_SECRET, } export { diff --git a/api/src/core/api.js b/api/src/core/api.js index 0bb6347a..27f87325 100644 --- a/api/src/core/api.js +++ b/api/src/core/api.js @@ -12,7 +12,8 @@ import { languageCode } from "../misc/utils.js"; import { createResponse, normalizeRequest, getIP } from "../processing/request.js"; import { verifyStream, getInternalStream } from "../stream/manage.js"; -import { randomizeCiphers } from '../misc/randomize-ciphers.js'; +import { randomizeCiphers } from "../misc/randomize-ciphers.js"; +import { verifyTurnstileToken } from "../misc/turnstile.js"; import { extract } from "../processing/url.js"; import match from "../processing/match.js"; import stream from "../stream/stream.js"; @@ -134,6 +135,23 @@ export function runAPI(express, app, __dirname) { return fail('ErrorNoLink'); } + if (env.turnstileSecret) { + const turnstileResponse = req.header("cf-turnstile-response"); + + if (!turnstileResponse) { + return fail("error.api.authentication"); + } + + const turnstileResult = await verifyTurnstileToken( + turnstileResponse, + req.ip + ); + + if (!turnstileResult) { + return fail("error.api.authentication"); + } + } + if (request.youtubeDubBrowserLang) { request.youtubeDubLang = lang; } diff --git a/api/src/misc/turnstile.js b/api/src/misc/turnstile.js new file mode 100644 index 00000000..bf4ffd86 --- /dev/null +++ b/api/src/misc/turnstile.js @@ -0,0 +1,19 @@ +import { env } from "../config.js"; + +export const verifyTurnstileToken = async (turnstileResponse, ip) => { + const result = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + secret: env.turnstileSecret, + response: turnstileResponse, + remoteip: ip, + }), + }) + .then(r => r.json()) + .catch(() => {}); + + return !!result?.success; +}