76 lines
2.1 KiB
JavaScript
76 lines
2.1 KiB
JavaScript
import "dotenv/config";
|
|
|
|
import bcrypt from "bcrypt";
|
|
|
|
const strictMode = process.env.REQUIRE_SECURITY !== "0";
|
|
const nodeEnv = (process.env.NODE_ENV || "").toLowerCase();
|
|
const allowPasswordSetup = process.env.INDIEKIT_ALLOW_PASSWORD_SETUP === "1";
|
|
|
|
function failOrWarn(message) {
|
|
if (strictMode) {
|
|
console.error(message);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.warn(`${message} Continuing because strict mode is disabled.`);
|
|
}
|
|
|
|
if (nodeEnv !== "production") {
|
|
failOrWarn(
|
|
`[preflight] NODE_ENV must be "production" for secure startup (received "${process.env.NODE_ENV || "(unset)"}").`,
|
|
);
|
|
}
|
|
|
|
if (process.env.INDIEKIT_ALLOW_DEV_AUTH === "1") {
|
|
failOrWarn(
|
|
"[preflight] INDIEKIT_ALLOW_DEV_AUTH=1 is not allowed in production.",
|
|
);
|
|
}
|
|
|
|
const secret = process.env.SECRET || "";
|
|
if (secret.length < 32) {
|
|
failOrWarn(
|
|
"[preflight] SECRET must be set and at least 32 characters long.",
|
|
);
|
|
}
|
|
|
|
const passwordSecret = process.env.PASSWORD_SECRET || "";
|
|
if (!passwordSecret) {
|
|
if (allowPasswordSetup) {
|
|
console.warn(
|
|
"[preflight] PASSWORD setup recovery mode enabled. Start app, generate a hash at /auth/new-password, then disable INDIEKIT_ALLOW_PASSWORD_SETUP.",
|
|
);
|
|
} else {
|
|
failOrWarn("[preflight] PASSWORD_SECRET is required.");
|
|
}
|
|
}
|
|
|
|
if (passwordSecret && !/^\$2[aby]\$\d{2}\$/.test(passwordSecret)) {
|
|
failOrWarn(
|
|
"[preflight] PASSWORD_SECRET must be a bcrypt hash (starts with $2a$, $2b$, or $2y$).",
|
|
);
|
|
}
|
|
|
|
try {
|
|
if (passwordSecret) {
|
|
const emptyPasswordValid = await bcrypt.compare("", passwordSecret);
|
|
if (emptyPasswordValid) {
|
|
failOrWarn(
|
|
"[preflight] PASSWORD_SECRET matches an empty password. Generate a non-empty password hash via /auth/new-password.",
|
|
);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
failOrWarn(
|
|
`[preflight] PASSWORD_SECRET could not be validated with bcrypt: ${error.message}`,
|
|
);
|
|
}
|
|
|
|
if (process.env.INDIEKIT_PASSWORD) {
|
|
console.warn(
|
|
"[preflight] INDIEKIT_PASSWORD is set but ignored by core auth. Use PASSWORD_SECRET only.",
|
|
);
|
|
}
|
|
|
|
console.log("[preflight] Production auth configuration OK");
|