mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:20:47 +00:00
turnstiel
This commit is contained in:
@@ -25,7 +25,6 @@ export enum GameEnv {
|
||||
|
||||
export interface ServerConfig {
|
||||
turnstileSiteKey(): string;
|
||||
turnstileSecretKey(): string;
|
||||
turnIntervalMs(): number;
|
||||
gameCreationRate(): number;
|
||||
numWorkers(): number;
|
||||
|
||||
@@ -43,9 +43,6 @@ const JwksSchema = z.object({
|
||||
});
|
||||
|
||||
export abstract class DefaultServerConfig implements ServerConfig {
|
||||
turnstileSecretKey(): string {
|
||||
return Env.TURNSTILE_SECRET_KEY ?? "";
|
||||
}
|
||||
abstract turnstileSiteKey(): string;
|
||||
allowedFlares(): string[] | undefined {
|
||||
return;
|
||||
|
||||
@@ -8,10 +8,6 @@ export class DevServerConfig extends DefaultServerConfig {
|
||||
return "1x00000000000000000000AA";
|
||||
}
|
||||
|
||||
turnstileSecretKey(): string {
|
||||
return "1x0000000000000000000000000000000AA";
|
||||
}
|
||||
|
||||
adminToken(): string {
|
||||
return "WARNING_DEV_ADMIN_KEY_DO_NOT_USE_IN_PRODUCTION";
|
||||
}
|
||||
|
||||
@@ -62,9 +62,6 @@ export const Env = {
|
||||
return getEnv("GAME_ENV") ?? "dev";
|
||||
},
|
||||
|
||||
get TURNSTILE_SECRET_KEY() {
|
||||
return getEnv("TURNSTILE_SECRET_KEY");
|
||||
},
|
||||
get STRIPE_PUBLISHABLE_KEY() {
|
||||
return getEnv("STRIPE_PUBLISHABLE_KEY");
|
||||
},
|
||||
|
||||
+21
-45
@@ -1,68 +1,44 @@
|
||||
import { ServerConfig } from "../core/configuration/Config";
|
||||
|
||||
type TurnstileResponse =
|
||||
| { status: "approved" }
|
||||
| { status: "rejected"; reason: string }
|
||||
| { status: "error"; reason: string };
|
||||
|
||||
export async function verifyTurnstileToken(
|
||||
ip: string,
|
||||
turnstileToken: string | null,
|
||||
turnstileSecret: string,
|
||||
): Promise<
|
||||
| { status: "approved" }
|
||||
| { status: "rejected"; reason: string }
|
||||
| { status: "error"; reason: string }
|
||||
> {
|
||||
if (!turnstileToken) {
|
||||
return { status: "rejected", reason: "No turnstile token provided" };
|
||||
}
|
||||
|
||||
config: ServerConfig,
|
||||
): Promise<TurnstileResponse> {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 3000);
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
const response = await fetch(
|
||||
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
secret: turnstileSecret,
|
||||
response: turnstileToken,
|
||||
remoteip: ip,
|
||||
}),
|
||||
signal: controller.signal,
|
||||
const response = await fetch(`${config.jwtIssuer()}/turnstile`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": config.apiKey(),
|
||||
},
|
||||
);
|
||||
body: JSON.stringify({ ip, token: turnstileToken }),
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
return {
|
||||
status: "error",
|
||||
reason: `Turnstile API returned ${response.status}`,
|
||||
reason: `api-worker returned ${response.status}`,
|
||||
};
|
||||
}
|
||||
|
||||
const result = (await response.json()) as {
|
||||
success: boolean;
|
||||
challenge_ts?: string;
|
||||
hostname?: string;
|
||||
"error-codes"?: string[];
|
||||
action?: string;
|
||||
cdata?: string;
|
||||
};
|
||||
|
||||
if (!result.success) {
|
||||
const codes = result["error-codes"]?.join(", ") ?? "unknown";
|
||||
return {
|
||||
status: "rejected",
|
||||
reason: `Turnstile token validation failed: ${codes}`,
|
||||
};
|
||||
}
|
||||
|
||||
return { status: "approved" };
|
||||
return (await response.json()) as TurnstileResponse;
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.name === "AbortError") {
|
||||
return {
|
||||
status: "error",
|
||||
reason: "Turnstile token validation timed out after 3 seconds",
|
||||
reason: "Turnstile token validation timed out after 5 seconds",
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -40,10 +40,6 @@ const workerId = parseInt(process.env.WORKER_ID ?? "0");
|
||||
const log = logger.child({ comp: `w_${workerId}` });
|
||||
const playlist = new MapPlaylist();
|
||||
|
||||
// TEMPORARY: Turnstile validation disabled while we diagnose intermittent
|
||||
// invalid-input-response rejections in v31. Flip back to true to re-enable.
|
||||
const TURNSTILE_ENABLED = false;
|
||||
|
||||
// Worker setup
|
||||
export async function startWorker() {
|
||||
log.info(`Worker starting...`);
|
||||
@@ -432,14 +428,11 @@ export async function startWorker() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TEMPORARY: Turnstile validation disabled while we diagnose
|
||||
// intermittent invalid-input-response rejections in v31.
|
||||
// Re-enable by flipping TURNSTILE_ENABLED back to true.
|
||||
if (TURNSTILE_ENABLED && config.env() !== GameEnv.Dev) {
|
||||
if (config.env() !== GameEnv.Dev) {
|
||||
const turnstileResult = await verifyTurnstileToken(
|
||||
ip,
|
||||
clientMsg.turnstileToken,
|
||||
config.turnstileSecretKey(),
|
||||
config,
|
||||
);
|
||||
switch (turnstileResult.status) {
|
||||
case "approved":
|
||||
|
||||
@@ -7,9 +7,6 @@ export class TestServerConfig implements ServerConfig {
|
||||
turnstileSiteKey(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
turnstileSecretKey(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
apiKey(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user