37 lines
1.8 KiB
JavaScript
37 lines
1.8 KiB
JavaScript
const LOGIN_URL_PATTERN = /https?:\/\/[^\s]+\/login\?[^\s]+/g;
|
|
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
|
|
export function parseMulticaLoginOutput(output) {
|
|
const matches = String(output || "").match(LOGIN_URL_PATTERN) || [];
|
|
const loginUrl = new URL(matches.at(-1) || "");
|
|
const callbackUrl = new URL(loginUrl.searchParams.get("cli_callback") || "");
|
|
const state = loginUrl.searchParams.get("cli_state") || "";
|
|
const port = Number(callbackUrl.port);
|
|
|
|
if (callbackUrl.protocol !== "http:" || !LOOPBACK_HOSTS.has(callbackUrl.hostname) || callbackUrl.pathname !== "/callback") {
|
|
throw new Error("Multica 尚未生成有效的本机回调地址");
|
|
}
|
|
if (!Number.isInteger(port) || port < 1024 || port > 65535 || !state) {
|
|
throw new Error("Multica 登录链接缺少端口或 state");
|
|
}
|
|
return { loginUrl, callbackUrl, state };
|
|
}
|
|
|
|
export function buildManagedMulticaLoginUrl(output, publicOrigin, sessionId) {
|
|
const { loginUrl } = parseMulticaLoginOutput(output);
|
|
const managedCallback = new URL(`/api/integrations/multica/oauth/callback/${encodeURIComponent(sessionId)}`, publicOrigin);
|
|
loginUrl.searchParams.set("cli_callback", managedCallback.toString());
|
|
return loginUrl.toString();
|
|
}
|
|
|
|
export function buildLocalMulticaCallbackUrl(output, query) {
|
|
const { callbackUrl, state } = parseMulticaLoginOutput(output);
|
|
const returnedState = typeof query?.state === "string" ? query.state : "";
|
|
const token = typeof query?.token === "string" ? query.token : "";
|
|
if (!token || !returnedState || returnedState !== state) throw new Error("Multica 回调校验失败,请重新发起验证");
|
|
callbackUrl.search = "";
|
|
callbackUrl.searchParams.set("token", token);
|
|
callbackUrl.searchParams.set("state", returnedState);
|
|
return callbackUrl.toString();
|
|
}
|