File size: 1,831 Bytes
cd2a4c2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import type { CookieOptions, Request } from "express";
const LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "::1"]);
function isIpAddress(host: string) {
// Basic IPv4 check and IPv6 presence detection.
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) return true;
return host.includes(":");
}
function isSecureRequest(req: Request) {
if (req.protocol === "https") return true;
const forwardedProto = req.headers["x-forwarded-proto"];
if (!forwardedProto) return false;
const protoList = Array.isArray(forwardedProto) ? forwardedProto : forwardedProto.split(",");
return protoList.some((proto) => proto.trim().toLowerCase() === "https");
}
/**
* Extract parent domain for cookie sharing across subdomains.
* e.g., "3000-xxx.manuspre.computer" -> ".manuspre.computer"
* This allows cookies set by 3000-xxx to be read by 8081-xxx
*/
function getParentDomain(hostname: string): string | undefined {
// Don't set domain for localhost or IP addresses
if (LOCAL_HOSTS.has(hostname) || isIpAddress(hostname)) {
return undefined;
}
// Split hostname into parts
const parts = hostname.split(".");
// Need at least 3 parts for a subdomain (e.g., "3000-xxx.manuspre.computer")
// For "manuspre.computer", we can't set a parent domain
if (parts.length < 3) {
return undefined;
}
// Return parent domain with leading dot (e.g., ".manuspre.computer")
// This allows cookie to be shared across all subdomains
return "." + parts.slice(-2).join(".");
}
export function getSessionCookieOptions(
req: Request,
): Pick<CookieOptions, "domain" | "httpOnly" | "path" | "sameSite" | "secure"> {
const hostname = req.hostname;
const domain = getParentDomain(hostname);
return {
domain,
httpOnly: true,
path: "/",
sameSite: "none",
secure: isSecureRequest(req),
};
}
|