mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:40:44 +00:00
use admin key token for admin auth
This commit is contained in:
@@ -72,6 +72,8 @@ export interface ServerConfig {
|
||||
workerPort(gameID: GameID): number;
|
||||
workerPortByIndex(workerID: number): number;
|
||||
env(): GameEnv;
|
||||
adminToken(): string;
|
||||
adminHeader(): string;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
|
||||
@@ -22,6 +22,12 @@ import { pastelTheme } from "./PastelTheme";
|
||||
import { pastelThemeDark } from "./PastelThemeDark";
|
||||
|
||||
export abstract class DefaultServerConfig implements ServerConfig {
|
||||
adminHeader(): string {
|
||||
return "x-admin-key";
|
||||
}
|
||||
adminToken(): string {
|
||||
return process.env.ADMIN_TOKEN;
|
||||
}
|
||||
numWorkers(): number {
|
||||
return 2;
|
||||
}
|
||||
@@ -183,7 +189,7 @@ export class DefaultConfig implements Config {
|
||||
return {
|
||||
cost: (p: Player) =>
|
||||
p.type() == PlayerType.Human && this.infiniteGold()
|
||||
? 0
|
||||
? 25
|
||||
: 25_000_000,
|
||||
territoryBound: false,
|
||||
};
|
||||
|
||||
@@ -5,9 +5,14 @@ import { GameEnv, ServerConfig } from "./Config";
|
||||
import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
|
||||
|
||||
export class DevServerConfig extends DefaultServerConfig {
|
||||
adminToken(): string {
|
||||
return "WARNING_DEV_ADMIN_KEY_DO_NOT_USE_IN_PRODUCTION";
|
||||
}
|
||||
|
||||
env(): GameEnv {
|
||||
return GameEnv.Dev;
|
||||
}
|
||||
|
||||
gameCreationRate(highTraffic: boolean): number {
|
||||
return 5 * 1000;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,6 @@ async function fetchLobbies(): Promise<void> {
|
||||
async function schedulePublicGame() {
|
||||
const gameID = generateID();
|
||||
publicLobbyIDs.add(gameID);
|
||||
|
||||
// Create the default public game config (from your GameManager)
|
||||
const defaultGameConfig = {
|
||||
gameMap: getNextMap(),
|
||||
@@ -192,9 +191,7 @@ async function schedulePublicGame() {
|
||||
disableNPCs: false,
|
||||
bots: 400,
|
||||
};
|
||||
|
||||
const workerPath = config.workerPath(gameID);
|
||||
|
||||
// Send request to the worker to start the game
|
||||
try {
|
||||
const response = await fetch(
|
||||
@@ -203,7 +200,8 @@ async function schedulePublicGame() {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Internal-Request": "true", // Special header for internal requests
|
||||
"X-Internal-Request": "true",
|
||||
[config.adminHeader()]: config.adminToken(),
|
||||
},
|
||||
body: JSON.stringify({
|
||||
gameID: gameID,
|
||||
@@ -211,11 +209,9 @@ async function schedulePublicGame() {
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to schedule public game: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
@@ -226,11 +222,9 @@ async function schedulePublicGame() {
|
||||
}
|
||||
}
|
||||
|
||||
// Map rotation management (moved from GameManager)
|
||||
let mapsPlaylist: GameMapType[] = [];
|
||||
const random = new PseudoRandom(123);
|
||||
|
||||
// Get the next map in rotation
|
||||
function getNextMap(): GameMapType {
|
||||
if (mapsPlaylist.length > 0) {
|
||||
return mapsPlaylist.shift()!;
|
||||
|
||||
+4
-25
@@ -79,9 +79,9 @@ export function startWorker() {
|
||||
// TODO: if game is public make sure request came from localhohst!!!
|
||||
const clientIP = req.ip || req.socket.remoteAddress || "unknown";
|
||||
const gc = req.body?.gameConfig as GameConfig;
|
||||
if (gc?.gameType == GameType.Public && !isLocalhost(req)) {
|
||||
if (gc?.gameType == GameType.Public && !isAdmin(req)) {
|
||||
console.warn(
|
||||
`cannot create public game ${id}, ip ${clientIP} not localhost`,
|
||||
`cannot create public game ${id}, ip ${clientIP} not admin`,
|
||||
);
|
||||
return res.status(400);
|
||||
}
|
||||
@@ -320,27 +320,6 @@ export function startWorker() {
|
||||
});
|
||||
}
|
||||
|
||||
const isLocalhost = (req: Request): boolean => {
|
||||
// Get client IP address from various possible sources
|
||||
const clientIP =
|
||||
req.ip ||
|
||||
req.socket.remoteAddress ||
|
||||
(req.headers["x-forwarded-for"] as string)?.split(",").shift() ||
|
||||
"unknown";
|
||||
|
||||
// Check if the request is from a loopback address
|
||||
const isLoopbackIP =
|
||||
// IPv4 localhost
|
||||
clientIP === "127.0.0.1" ||
|
||||
// IPv6 localhost
|
||||
clientIP === "::1" ||
|
||||
// Full loopback range
|
||||
clientIP.startsWith("127.");
|
||||
|
||||
// Check hostname
|
||||
const isLocalHostname =
|
||||
req.hostname === "localhost" || req.headers.host?.startsWith("localhost:");
|
||||
|
||||
// Consider request local if either IP is loopback or hostname is localhost
|
||||
return isLoopbackIP || isLocalHostname;
|
||||
const isAdmin = (req: Request): boolean => {
|
||||
return req.headers[config.adminHeader()] === config.adminToken();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user