mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-09 05:11:31 +00:00
99 lines
3.0 KiB
JavaScript
99 lines
3.0 KiB
JavaScript
// The server this desktop is linked to, as the embedded backend reports it.
|
|
// The backend owns the link (and its secrets); main only keeps what it needs
|
|
// to reach that one origin: the proxy headers and basic auth a reverse proxy
|
|
// in front of it wants, whether its certificate may be self-signed, and the
|
|
// session for requests main makes itself (C2S tunnels).
|
|
|
|
let linked = null;
|
|
|
|
function getOrigin(url) {
|
|
try {
|
|
return new URL(url).origin;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function setLinkedServer(config) {
|
|
if (!config || !config.origin) {
|
|
linked = null;
|
|
return;
|
|
}
|
|
linked = {
|
|
origin: config.origin,
|
|
serverUrl: config.serverUrl || config.origin,
|
|
token: config.token || null,
|
|
headers: Array.isArray(config.headers) ? config.headers : [],
|
|
basicAuth:
|
|
config.basicAuth && config.basicAuth.username ? config.basicAuth : null,
|
|
allowInvalidCertificate: !!config.allowInvalidCertificate,
|
|
};
|
|
}
|
|
|
|
function getLinkedServer() {
|
|
return linked;
|
|
}
|
|
|
|
function isLinkedOrigin(url) {
|
|
return !!linked && getOrigin(url) === linked.origin;
|
|
}
|
|
|
|
function basicAuthValue(basicAuth) {
|
|
return `Basic ${Buffer.from(
|
|
`${basicAuth.username}:${basicAuth.password || ""}`,
|
|
).toString("base64")}`;
|
|
}
|
|
|
|
// Adds the link's proxy headers to a request bound for the linked origin.
|
|
// With basic auth in front, Authorization belongs to the proxy, so a Termix
|
|
// bearer token moves into the jwt cookie, which Termix reads first.
|
|
function applyLinkHeaders(url, headers) {
|
|
if (!isLinkedOrigin(url)) return headers;
|
|
const out = { ...headers };
|
|
for (const header of linked.headers) {
|
|
if (header && header.name && header.value) out[header.name] = header.value;
|
|
}
|
|
if (linked.basicAuth) {
|
|
const authKey = Object.keys(out).find(
|
|
(key) => key.toLowerCase() === "authorization",
|
|
);
|
|
const current = authKey ? String(out[authKey]) : "";
|
|
if (authKey) delete out[authKey];
|
|
const bearer = current.match(/^Bearer\s+(.+)$/i);
|
|
if (bearer) {
|
|
const cookieKey =
|
|
Object.keys(out).find((key) => key.toLowerCase() === "cookie") ||
|
|
"Cookie";
|
|
const existing = out[cookieKey] ? `${out[cookieKey]}; ` : "";
|
|
out[cookieKey] = `${existing}jwt=${bearer[1]}`;
|
|
}
|
|
out.Authorization = basicAuthValue(linked.basicAuth);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// Headers for a request main itself makes to the linked server.
|
|
function linkedRequestHeaders(extra = {}) {
|
|
if (!linked) return { ...extra };
|
|
const base = { "X-Electron-App": "true", ...extra };
|
|
if (linked.token) base.Authorization = `Bearer ${linked.token}`;
|
|
return applyLinkHeaders(linked.origin, base);
|
|
}
|
|
|
|
// Answers a basic auth challenge from the linked origin's proxy.
|
|
function answerLogin(authInfo, url) {
|
|
if (!linked || !linked.basicAuth) return null;
|
|
if (authInfo && authInfo.isProxy) return null;
|
|
if (!isLinkedOrigin(url)) return null;
|
|
return linked.basicAuth;
|
|
}
|
|
|
|
module.exports = {
|
|
setLinkedServer,
|
|
getLinkedServer,
|
|
isLinkedOrigin,
|
|
applyLinkHeaders,
|
|
linkedRequestHeaders,
|
|
answerLogin,
|
|
};
|