Fix authenticated BIM share promotion
This commit is contained in:
+47
-2
@@ -56,6 +56,7 @@ const BIM_SESSION_COOKIE = process.env.NODEDC_BIM_SESSION_COOKIE || "nodedc_bim_
|
||||
const BIM_SESSION_TTL_MS = Number(process.env.NODEDC_BIM_SESSION_TTL_MS || 12 * 60 * 60 * 1000);
|
||||
const BIM_COOKIE_SECURE = parseBooleanEnv(process.env.NODEDC_BIM_COOKIE_SECURE, false);
|
||||
const BIM_COOKIE_SAMESITE = process.env.NODEDC_BIM_COOKIE_SAMESITE || (BIM_COOKIE_SECURE ? "None" : "Lax");
|
||||
const SHARE_AUTH_GUEST_PARAM = "ndc_bim_guest";
|
||||
const CORS_ALLOWED_ORIGINS = String(process.env.NODEDC_BIM_ALLOWED_ORIGINS || "")
|
||||
.split(",")
|
||||
.map((origin) => origin.trim())
|
||||
@@ -812,6 +813,14 @@ const buildLauncherLaunchUrl = (nextPath = "/") => {
|
||||
return launchUrl.toString();
|
||||
};
|
||||
|
||||
const buildLauncherOptionalLaunchUrl = (nextPath = "/", fallbackPath = nextPath) => {
|
||||
const launchPath = `/api/services/${encodeURIComponent(BIM_SERVICE_SLUG)}/optional-launch`;
|
||||
const launchUrl = new URL(launchPath, LAUNCHER_BASE_URL);
|
||||
launchUrl.searchParams.set("returnTo", sanitizeReturnTo(nextPath));
|
||||
launchUrl.searchParams.set("fallbackTo", sanitizeReturnTo(fallbackPath, nextPath));
|
||||
return launchUrl.toString();
|
||||
};
|
||||
|
||||
const buildLauncherLoginUrl = (req, nextPath = "/") => {
|
||||
const loginUrl = new URL("/auth/login", LAUNCHER_BASE_URL);
|
||||
const launchUrl = new URL(buildLauncherLaunchUrl(nextPath));
|
||||
@@ -822,16 +831,47 @@ const buildLauncherLoginUrl = (req, nextPath = "/") => {
|
||||
const buildSharePromotionUrls = (token) => {
|
||||
const safeToken = safeShareToken(token);
|
||||
if (!safeToken) {
|
||||
return {promoteUrl: null, silentPromoteUrl: null};
|
||||
return {promoteUrl: null, silentPromoteUrl: null, optionalPromoteUrl: null};
|
||||
}
|
||||
const sharePath = `/share/${encodeURIComponent(safeToken)}`;
|
||||
const guestPath = `${sharePath}?${SHARE_AUTH_GUEST_PARAM}=1`;
|
||||
const bridgePath = `/auth/share-promoted?next=${encodeURIComponent(sharePath)}`;
|
||||
return {
|
||||
promoteUrl: buildLauncherLaunchUrl(sharePath),
|
||||
silentPromoteUrl: buildLauncherLaunchUrl(bridgePath)
|
||||
silentPromoteUrl: buildLauncherLaunchUrl(bridgePath),
|
||||
optionalPromoteUrl: buildLauncherOptionalLaunchUrl(sharePath, guestPath)
|
||||
};
|
||||
};
|
||||
|
||||
const shouldPromoteShareNavigation = (req, url) => {
|
||||
if (!BIM_AUTH_REQUIRED || !INTERNAL_ACCESS_TOKEN || !isPublicSharePath(url)) {
|
||||
return false;
|
||||
}
|
||||
if (req.method !== "GET" && req.method !== "HEAD") {
|
||||
return false;
|
||||
}
|
||||
if (url.searchParams.get(SHARE_AUTH_GUEST_PARAM) === "1") {
|
||||
return false;
|
||||
}
|
||||
if (getCurrentBimSession(req)) {
|
||||
return false;
|
||||
}
|
||||
const accept = typeof req.headers.accept === "string" ? req.headers.accept : "";
|
||||
return accept.includes("text/html") || accept.includes("*/*") || !accept;
|
||||
};
|
||||
|
||||
const redirectShareNavigationToPromotion = (res, token) => {
|
||||
const urls = buildSharePromotionUrls(token);
|
||||
if (!urls.optionalPromoteUrl) {
|
||||
return false;
|
||||
}
|
||||
res.statusCode = 302;
|
||||
res.setHeader("Location", urls.optionalPromoteUrl);
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
res.end();
|
||||
return true;
|
||||
};
|
||||
|
||||
const sendAuthRequired = (req, res, url) => {
|
||||
const nextPath = sanitizeReturnTo(`${url.pathname}${url.search || ""}`);
|
||||
if (!INTERNAL_ACCESS_TOKEN) {
|
||||
@@ -1777,6 +1817,7 @@ const handleGetShare = async (req, res, token) => {
|
||||
canShare: !BIM_AUTH_REQUIRED || authenticated,
|
||||
promoteUrl: promotionUrls.promoteUrl,
|
||||
silentPromoteUrl: promotionUrls.silentPromoteUrl,
|
||||
optionalPromoteUrl: promotionUrls.optionalPromoteUrl,
|
||||
user: session?.user || null,
|
||||
viewer: {
|
||||
src: publicUrlForUploadSrc(req, share.src),
|
||||
@@ -3267,6 +3308,10 @@ const requestHandler = async (req, res) => {
|
||||
return handleGetShare(req, res, shareTokenFromPath(url.pathname));
|
||||
}
|
||||
|
||||
if (shouldPromoteShareNavigation(req, url) && redirectShareNavigationToPromotion(res, shareTokenFromPath(url.pathname))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ensureBimSessionForRequest(req, res, url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user