ИСПРАВЛЕНИЕ - NODEDC LAUNCHER: restore reliable IdP logout handoff
This commit is contained in:
parent
96e6a97d38
commit
6e8b05c679
|
|
@ -167,6 +167,20 @@ app.get("/auth/session-sync", (req, res) => {
|
||||||
res.type("html").send(renderSessionSyncBridgePage(allowedOrigins));
|
res.type("html").send(renderSessionSyncBridgePage(allowedOrigins));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/logout", (req, res) => {
|
||||||
|
const session = getCurrentSession(req);
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
sessions.delete(session.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.clearCookie(sessionCookieName, clearCookieOptions());
|
||||||
|
setNoStore(res);
|
||||||
|
res.type("html").send(
|
||||||
|
"<!doctype html><html><head><meta charset='utf-8'></head><body>NODE.DC Launcher session closed.</body></html>"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
app.get("/auth/logout", asyncRoute(async (req, res) => {
|
app.get("/auth/logout", asyncRoute(async (req, res) => {
|
||||||
const session = getCurrentSession(req);
|
const session = getCurrentSession(req);
|
||||||
const returnTo = sanitizeReturnTo(req.query.returnTo);
|
const returnTo = sanitizeReturnTo(req.query.returnTo);
|
||||||
|
|
@ -188,21 +202,19 @@ app.get("/auth/logout", asyncRoute(async (req, res) => {
|
||||||
const endSessionEndpoint = discovery.end_session_endpoint;
|
const endSessionEndpoint = discovery.end_session_endpoint;
|
||||||
const loginRedirectUrl = buildLoginRedirectUrl(returnTo, { forceLogin: true });
|
const loginRedirectUrl = buildLoginRedirectUrl(returnTo, { forceLogin: true });
|
||||||
|
|
||||||
if (!endSessionEndpoint) {
|
if (!endSessionEndpoint || !session?.tokenSet.idToken) {
|
||||||
setNoStore(res);
|
setNoStore(res);
|
||||||
res.type("html").send(renderGlobalLogoutPage(getFrontchannelLogoutUrls(), null, loginRedirectUrl));
|
res.type("html").send(renderGlobalLogoutPage(getFrontchannelLogoutUrls(), loginRedirectUrl));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const logoutUrl = new URL(endSessionEndpoint);
|
const logoutUrl = new URL(endSessionEndpoint);
|
||||||
logoutUrl.searchParams.set("client_id", config.clientId);
|
logoutUrl.searchParams.set("client_id", config.clientId);
|
||||||
|
logoutUrl.searchParams.set("post_logout_redirect_uri", buildLoggedOutRedirectUrl(returnTo));
|
||||||
if (session?.tokenSet.idToken) {
|
logoutUrl.searchParams.set("id_token_hint", session.tokenSet.idToken);
|
||||||
logoutUrl.searchParams.set("id_token_hint", session.tokenSet.idToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
setNoStore(res);
|
setNoStore(res);
|
||||||
res.type("html").send(renderGlobalLogoutPage(getFrontchannelLogoutUrls(), logoutUrl.toString(), loginRedirectUrl));
|
res.type("html").send(renderGlobalLogoutPage(getFrontchannelLogoutUrls(), logoutUrl.toString()));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.get("/api/me", (req, res) => {
|
app.get("/api/me", (req, res) => {
|
||||||
|
|
@ -949,9 +961,8 @@ function normalizeLogoutUrl(value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGlobalLogoutPage(frontchannelLogoutUrls, identityProviderLogoutUrl, finalRedirectUrl) {
|
function renderGlobalLogoutPage(frontchannelLogoutUrls, finalRedirectUrl) {
|
||||||
const logoutUrlsJson = JSON.stringify(frontchannelLogoutUrls);
|
const logoutUrlsJson = JSON.stringify(frontchannelLogoutUrls);
|
||||||
const identityProviderLogoutUrlJson = JSON.stringify(identityProviderLogoutUrl);
|
|
||||||
const redirectUrlJson = JSON.stringify(finalRedirectUrl);
|
const redirectUrlJson = JSON.stringify(finalRedirectUrl);
|
||||||
|
|
||||||
return `<!doctype html>
|
return `<!doctype html>
|
||||||
|
|
@ -989,7 +1000,6 @@ function renderGlobalLogoutPage(frontchannelLogoutUrls, identityProviderLogoutUr
|
||||||
localStorage.setItem("nodedc:platform-session-event", JSON.stringify(eventPayload));
|
localStorage.setItem("nodedc:platform-session-event", JSON.stringify(eventPayload));
|
||||||
} catch {}
|
} catch {}
|
||||||
const logoutUrls = ${logoutUrlsJson};
|
const logoutUrls = ${logoutUrlsJson};
|
||||||
const identityProviderLogoutUrl = ${identityProviderLogoutUrlJson};
|
|
||||||
const finalRedirectUrl = ${redirectUrlJson};
|
const finalRedirectUrl = ${redirectUrlJson};
|
||||||
for (const logoutUrl of logoutUrls) {
|
for (const logoutUrl of logoutUrls) {
|
||||||
fetch(logoutUrl, { mode: "no-cors", credentials: "include", keepalive: true }).catch(() => undefined);
|
fetch(logoutUrl, { mode: "no-cors", credentials: "include", keepalive: true }).catch(() => undefined);
|
||||||
|
|
@ -997,21 +1007,6 @@ function renderGlobalLogoutPage(frontchannelLogoutUrls, identityProviderLogoutUr
|
||||||
image.referrerPolicy = "no-referrer";
|
image.referrerPolicy = "no-referrer";
|
||||||
image.src = logoutUrl;
|
image.src = logoutUrl;
|
||||||
}
|
}
|
||||||
if (identityProviderLogoutUrl) {
|
|
||||||
fetch(identityProviderLogoutUrl, { mode: "no-cors", credentials: "include", keepalive: true }).catch(() => undefined);
|
|
||||||
const iframe = document.createElement("iframe");
|
|
||||||
iframe.title = "NODE.DC identity logout";
|
|
||||||
iframe.tabIndex = -1;
|
|
||||||
iframe.setAttribute("aria-hidden", "true");
|
|
||||||
iframe.style.position = "fixed";
|
|
||||||
iframe.style.width = "0";
|
|
||||||
iframe.style.height = "0";
|
|
||||||
iframe.style.opacity = "0";
|
|
||||||
iframe.style.pointerEvents = "none";
|
|
||||||
iframe.style.border = "0";
|
|
||||||
iframe.src = identityProviderLogoutUrl;
|
|
||||||
document.body.appendChild(iframe);
|
|
||||||
}
|
|
||||||
window.setTimeout(() => window.location.replace(finalRedirectUrl), 1200);
|
window.setTimeout(() => window.location.replace(finalRedirectUrl), 1200);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
@ -1459,6 +1454,17 @@ function buildLoginRedirectUrl(returnTo, { forceLogin = false } = {}) {
|
||||||
return loginUrl.toString();
|
return loginUrl.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildLoggedOutRedirectUrl(returnTo = "/") {
|
||||||
|
const loggedOutUrl = new URL("/auth/logged-out", config.appBaseUrl);
|
||||||
|
const cleanReturnTo = sanitizeReturnTo(returnTo);
|
||||||
|
|
||||||
|
if (cleanReturnTo !== "/") {
|
||||||
|
loggedOutUrl.searchParams.set("returnTo", cleanReturnTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loggedOutUrl.toString();
|
||||||
|
}
|
||||||
|
|
||||||
function randomBase64Url(size) {
|
function randomBase64Url(size) {
|
||||||
return randomBytes(size).toString("base64url");
|
return randomBytes(size).toString("base64url");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue