Publish Launcher login session events

This commit is contained in:
DCCONSTRUCTIONS 2026-06-23 18:57:23 +03:00
parent 71c62579dc
commit 1b58246897
1 changed files with 44 additions and 6 deletions

View File

@ -213,7 +213,8 @@ app.get("/auth/callback", asyncRoute(async (req, res) => {
accessToken: tokenSet.access_token ?? null, accessToken: tokenSet.access_token ?? null,
expiresAt: tokenSet.expires_in ? Date.now() + Number(tokenSet.expires_in) * 1000 : null, expiresAt: tokenSet.expires_in ? Date.now() + Number(tokenSet.expires_in) * 1000 : null,
}); });
res.redirect(pendingLogin.returnTo); setNoStore(res);
res.type("html").send(renderLoginCompletePage(pendingLogin.returnTo));
})); }));
app.get("/auth/logged-out", (req, res) => { app.get("/auth/logged-out", (req, res) => {
@ -4015,6 +4016,41 @@ function renderGlobalLogoutPage(frontchannelLogoutUrls, finalRedirectUrl) {
</html>`; </html>`;
} }
function renderLoginCompletePage(returnTo) {
const redirectUrlJson = JSON.stringify(sanitizeReturnTo(returnTo));
return `<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>NODE.DC</title>
<style>
html,body{height:100%;margin:0;background:#0b0f0e;color:#0b0f0e}
</style>
</head>
<body aria-busy="true">
<script>
const eventPayload = {
type: "nodedc:session:login",
id: globalThis.crypto?.randomUUID ? globalThis.crypto.randomUUID() : String(Date.now()) + "-" + Math.random().toString(36).slice(2),
source: "launcher-login",
createdAt: Date.now()
};
try {
const channel = new BroadcastChannel("nodedc-platform-session");
channel.postMessage(eventPayload);
channel.close();
} catch {}
try {
localStorage.setItem("nodedc:platform-session-event", JSON.stringify(eventPayload));
} catch {}
window.setTimeout(() => window.location.replace(${redirectUrlJson}), 30);
</script>
</body>
</html>`;
}
function renderSessionSyncBridgePage(allowedOrigins) { function renderSessionSyncBridgePage(allowedOrigins) {
const allowedOriginsJson = JSON.stringify(allowedOrigins); const allowedOriginsJson = JSON.stringify(allowedOrigins);
@ -4043,18 +4079,20 @@ function renderSessionSyncBridgePage(allowedOrigins) {
return allowedOrigins.has(origin); return allowedOrigins.has(origin);
} }
function isLogoutEvent(payload) { function isSessionEvent(payload) {
return payload && payload.type === "nodedc:session:logout" && typeof payload.id === "string"; return payload &&
(payload.type === "nodedc:session:logout" || payload.type === "nodedc:session:login") &&
typeof payload.id === "string";
} }
function forwardToParent(payload) { function forwardToParent(payload) {
if (!isLogoutEvent(payload) || payload.id === lastEventId || !isAllowedOrigin(parentOrigin)) return; if (!isSessionEvent(payload) || payload.id === lastEventId || !isAllowedOrigin(parentOrigin)) return;
lastEventId = payload.id; lastEventId = payload.id;
window.parent.postMessage(payload, parentOrigin); window.parent.postMessage(payload, parentOrigin);
} }
function publish(payload) { function publish(payload) {
if (!isLogoutEvent(payload)) return; if (!isSessionEvent(payload)) return;
try { try {
const channel = new BroadcastChannel(channelName); const channel = new BroadcastChannel(channelName);
channel.postMessage(payload); channel.postMessage(payload);
@ -4066,7 +4104,7 @@ function renderSessionSyncBridgePage(allowedOrigins) {
} }
window.addEventListener("message", (event) => { window.addEventListener("message", (event) => {
if (!isAllowedOrigin(event.origin) || !isLogoutEvent(event.data)) return; if (!isAllowedOrigin(event.origin) || !isSessionEvent(event.data)) return;
publish(event.data); publish(event.data);
}); });