Files
overlord/Overlord-Server/src/server/agent-auth.ts
T

49 lines
1.4 KiB
TypeScript
Raw Normal View History

2026-03-05 00:04:26 -06:00
import { logger } from "../logger";
2026-03-21 17:03:42 -05:00
import { timingSafeEqual } from "crypto";
function safeCompare(a: string, b: string): boolean {
const bufA = Buffer.from(a);
const bufB = Buffer.from(b);
if (bufA.length !== bufB.length) return false;
return timingSafeEqual(bufA, bufB);
}
2026-03-05 00:04:26 -06:00
export function isAuthorizedAgentRequest(
req: Request,
url: URL,
agentToken?: string,
): boolean {
const disableAuth =
String(process.env.OVERLORD_DISABLE_AGENT_AUTH || "").toLowerCase() ===
"true";
if (disableAuth) {
const nodeEnv = String(process.env.NODE_ENV || "development").toLowerCase();
if (nodeEnv === "production") {
logger.warn("[auth] OVERLORD_DISABLE_AGENT_AUTH is ignored in production mode");
} else {
logger.info("[auth] Agent auth explicitly disabled by OVERLORD_DISABLE_AGENT_AUTH=true (non-production mode)");
return true;
}
2026-03-05 00:04:26 -06:00
}
const token = agentToken?.trim();
if (!token) {
logger.info("[auth] Agent auth disabled");
return true;
}
const headerToken = req.headers.get("x-agent-token");
const queryToken = url.searchParams.get("token");
2026-03-21 17:03:42 -05:00
const isAuthed =
(headerToken !== null && safeCompare(headerToken, token)) ||
(queryToken !== null && safeCompare(queryToken, token));
2026-03-05 00:04:26 -06:00
if (!isAuthed) {
logger.info("[auth] Agent auth failed");
} else {
logger.info("[auth] Agent authenticated successfully");
}
return isAuthed;
}