ФУНКЦИИ - NODEDC LAUNCHER: use top-level IdP logout
This commit is contained in:
parent
ab1e0856d6
commit
bf32313177
|
|
@ -136,6 +136,15 @@ app.get("/auth/callback", asyncRoute(async (req, res) => {
|
||||||
res.redirect(pendingLogin.returnTo);
|
res.redirect(pendingLogin.returnTo);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
app.get("/auth/logged-out", (req, res) => {
|
||||||
|
const returnTo = sanitizeReturnTo(req.query.returnTo);
|
||||||
|
|
||||||
|
res.clearCookie(sessionCookieName, clearCookieOptions());
|
||||||
|
res.clearCookie(oidcStateCookieName, clearCookieOptions());
|
||||||
|
setNoStore(res);
|
||||||
|
res.redirect(buildLoginRedirectUrl(returnTo, { forceLogin: true }));
|
||||||
|
});
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -156,6 +165,7 @@ app.get("/auth/logout", asyncRoute(async (req, res) => {
|
||||||
const discovery = await getOidcDiscovery();
|
const discovery = await getOidcDiscovery();
|
||||||
const endSessionEndpoint = discovery.end_session_endpoint;
|
const endSessionEndpoint = discovery.end_session_endpoint;
|
||||||
const loginRedirectUrl = buildLoginRedirectUrl(returnTo, { forceLogin: true });
|
const loginRedirectUrl = buildLoginRedirectUrl(returnTo, { forceLogin: true });
|
||||||
|
const postLogoutRedirectUrl = buildLoggedOutRedirectUrl();
|
||||||
|
|
||||||
if (!endSessionEndpoint) {
|
if (!endSessionEndpoint) {
|
||||||
setNoStore(res);
|
setNoStore(res);
|
||||||
|
|
@ -165,14 +175,14 @@ app.get("/auth/logout", asyncRoute(async (req, res) => {
|
||||||
|
|
||||||
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", loginRedirectUrl);
|
logoutUrl.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUrl);
|
||||||
|
|
||||||
if (session?.tokenSet.idToken) {
|
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(), loginRedirectUrl, logoutUrl.toString()));
|
res.type("html").send(renderGlobalLogoutPage(getFrontchannelLogoutUrls(), logoutUrl.toString()));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.get("/api/me", (req, res) => {
|
app.get("/api/me", (req, res) => {
|
||||||
|
|
@ -548,6 +558,7 @@ function readConfig() {
|
||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
redirectUri: process.env.LAUNCHER_OIDC_REDIRECT_URI ?? `${appBaseUrl}/auth/callback`,
|
redirectUri: process.env.LAUNCHER_OIDC_REDIRECT_URI ?? `${appBaseUrl}/auth/callback`,
|
||||||
|
loggedOutRedirectUri: process.env.LAUNCHER_OIDC_LOGGED_OUT_REDIRECT_URI ?? `${appBaseUrl}/auth/logged-out`,
|
||||||
appBaseUrl,
|
appBaseUrl,
|
||||||
scope: process.env.LAUNCHER_OIDC_SCOPE ?? "openid email profile groups offline_access",
|
scope: process.env.LAUNCHER_OIDC_SCOPE ?? "openid email profile groups offline_access",
|
||||||
cookieDomain: process.env.LAUNCHER_COOKIE_DOMAIN || undefined,
|
cookieDomain: process.env.LAUNCHER_COOKIE_DOMAIN || undefined,
|
||||||
|
|
@ -919,10 +930,9 @@ function normalizeLogoutUrl(value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGlobalLogoutPage(frontchannelLogoutUrls, finalRedirectUrl, identityLogoutUrl = null) {
|
function renderGlobalLogoutPage(frontchannelLogoutUrls, finalRedirectUrl) {
|
||||||
const logoutUrlsJson = JSON.stringify(frontchannelLogoutUrls);
|
const logoutUrlsJson = JSON.stringify(frontchannelLogoutUrls);
|
||||||
const redirectUrlJson = JSON.stringify(finalRedirectUrl);
|
const redirectUrlJson = JSON.stringify(finalRedirectUrl);
|
||||||
const identityLogoutUrlJson = JSON.stringify(identityLogoutUrl);
|
|
||||||
|
|
||||||
return `<!doctype html>
|
return `<!doctype html>
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
|
|
@ -946,19 +956,12 @@ function renderGlobalLogoutPage(frontchannelLogoutUrls, finalRedirectUrl, identi
|
||||||
<script>
|
<script>
|
||||||
const logoutUrls = ${logoutUrlsJson};
|
const logoutUrls = ${logoutUrlsJson};
|
||||||
const finalRedirectUrl = ${redirectUrlJson};
|
const finalRedirectUrl = ${redirectUrlJson};
|
||||||
const identityLogoutUrl = ${identityLogoutUrlJson};
|
|
||||||
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);
|
||||||
const image = new Image();
|
const image = new Image();
|
||||||
image.referrerPolicy = "no-referrer";
|
image.referrerPolicy = "no-referrer";
|
||||||
image.src = logoutUrl;
|
image.src = logoutUrl;
|
||||||
}
|
}
|
||||||
if (identityLogoutUrl) {
|
|
||||||
fetch(identityLogoutUrl, { mode: "no-cors", credentials: "include", keepalive: true }).catch(() => undefined);
|
|
||||||
const identityImage = new Image();
|
|
||||||
identityImage.referrerPolicy = "no-referrer";
|
|
||||||
identityImage.src = identityLogoutUrl;
|
|
||||||
}
|
|
||||||
window.setTimeout(() => window.location.replace(finalRedirectUrl), 900);
|
window.setTimeout(() => window.location.replace(finalRedirectUrl), 900);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
@ -1284,6 +1287,11 @@ function buildLoginRedirectUrl(returnTo, { forceLogin = false } = {}) {
|
||||||
return loginUrl.toString();
|
return loginUrl.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildLoggedOutRedirectUrl() {
|
||||||
|
const loggedOutUrl = new URL(config.loggedOutRedirectUri);
|
||||||
|
return loggedOutUrl.toString();
|
||||||
|
}
|
||||||
|
|
||||||
function randomBase64Url(size) {
|
function randomBase64Url(size) {
|
||||||
return randomBytes(size).toString("base64url");
|
return randomBytes(size).toString("base64url");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue