fix(webui): gate bootstrap API token issuance
This commit is contained in:
@@ -2,6 +2,7 @@ import type { BootstrapResponse } from "./types";
|
||||
import { fetchWithTimeout } from "./http";
|
||||
|
||||
const SECRET_STORAGE_KEY = "nanobot-webui.bootstrap-secret";
|
||||
const URL_SECRET_PARAM = "bootstrapSecret";
|
||||
|
||||
/** Read a previously saved bootstrap secret from localStorage. */
|
||||
export function loadSavedSecret(): string {
|
||||
@@ -31,6 +32,29 @@ export function clearSavedSecret(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function consumeUrlBootstrapSecret(): string {
|
||||
if (typeof window === "undefined") return "";
|
||||
const hash = window.location.hash || "";
|
||||
const queryStart = hash.indexOf("?");
|
||||
if (queryStart < 0) return "";
|
||||
|
||||
const path = hash.slice(0, queryStart) || "#/";
|
||||
const query = hash.slice(queryStart + 1);
|
||||
const params = new URLSearchParams(query);
|
||||
const secret = params.get(URL_SECRET_PARAM)?.trim() || "";
|
||||
if (!secret) return "";
|
||||
|
||||
params.delete(URL_SECRET_PARAM);
|
||||
const nextQuery = params.toString();
|
||||
const nextHash = `${path}${nextQuery ? `?${nextQuery}` : ""}`;
|
||||
window.history.replaceState(
|
||||
null,
|
||||
"",
|
||||
`${window.location.pathname}${window.location.search}${nextHash}`,
|
||||
);
|
||||
return secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a short-lived token + the WebSocket path from the gateway's
|
||||
* ``/webui/bootstrap`` endpoint.
|
||||
@@ -56,6 +80,9 @@ export async function fetchBootstrap(
|
||||
if (!body.token || !body.ws_path) {
|
||||
throw new Error("bootstrap response missing token or ws_path");
|
||||
}
|
||||
if (!body.api_token) {
|
||||
throw new Error("bootstrap response missing api_token");
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@ export interface SidebarStatePayload {
|
||||
|
||||
export interface BootstrapResponse {
|
||||
token: string;
|
||||
api_token: string;
|
||||
ws_path: string;
|
||||
ws_url?: string | null;
|
||||
expires_in: number;
|
||||
|
||||
Reference in New Issue
Block a user