mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 05:37:27 +00:00
refactor(gateway): extract ws auth message helpers
This commit is contained in:
79
src/gateway/server/ws-connection/auth-messages.ts
Normal file
79
src/gateway/server/ws-connection/auth-messages.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import type { ResolvedGatewayAuth } from "../../auth.js";
|
||||||
|
import { isGatewayCliClient, isWebchatClient } from "../../../utils/message-channel.js";
|
||||||
|
import { GATEWAY_CLIENT_IDS } from "../../protocol/client-info.js";
|
||||||
|
|
||||||
|
export type AuthProvidedKind = "token" | "password" | "none";
|
||||||
|
|
||||||
|
export function resolveHostName(hostHeader?: string): string {
|
||||||
|
const host = (hostHeader ?? "").trim().toLowerCase();
|
||||||
|
if (!host) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (host.startsWith("[")) {
|
||||||
|
const end = host.indexOf("]");
|
||||||
|
if (end !== -1) {
|
||||||
|
return host.slice(1, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [name] = host.split(":");
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatGatewayAuthFailureMessage(params: {
|
||||||
|
authMode: ResolvedGatewayAuth["mode"];
|
||||||
|
authProvided: AuthProvidedKind;
|
||||||
|
reason?: string;
|
||||||
|
client?: { id?: string | null; mode?: string | null };
|
||||||
|
}): string {
|
||||||
|
const { authMode, authProvided, reason, client } = params;
|
||||||
|
const isCli = isGatewayCliClient(client);
|
||||||
|
const isControlUi = client?.id === GATEWAY_CLIENT_IDS.CONTROL_UI;
|
||||||
|
const isWebchat = isWebchatClient(client);
|
||||||
|
const uiHint = "open the dashboard URL and paste the token in Control UI settings";
|
||||||
|
const tokenHint = isCli
|
||||||
|
? "set gateway.remote.token to match gateway.auth.token"
|
||||||
|
: isControlUi || isWebchat
|
||||||
|
? uiHint
|
||||||
|
: "provide gateway auth token";
|
||||||
|
const passwordHint = isCli
|
||||||
|
? "set gateway.remote.password to match gateway.auth.password"
|
||||||
|
: isControlUi || isWebchat
|
||||||
|
? "enter the password in Control UI settings"
|
||||||
|
: "provide gateway auth password";
|
||||||
|
switch (reason) {
|
||||||
|
case "token_missing":
|
||||||
|
return `unauthorized: gateway token missing (${tokenHint})`;
|
||||||
|
case "token_mismatch":
|
||||||
|
return `unauthorized: gateway token mismatch (${tokenHint})`;
|
||||||
|
case "token_missing_config":
|
||||||
|
return "unauthorized: gateway token not configured on gateway (set gateway.auth.token)";
|
||||||
|
case "password_missing":
|
||||||
|
return `unauthorized: gateway password missing (${passwordHint})`;
|
||||||
|
case "password_mismatch":
|
||||||
|
return `unauthorized: gateway password mismatch (${passwordHint})`;
|
||||||
|
case "password_missing_config":
|
||||||
|
return "unauthorized: gateway password not configured on gateway (set gateway.auth.password)";
|
||||||
|
case "tailscale_user_missing":
|
||||||
|
return "unauthorized: tailscale identity missing (use Tailscale Serve auth or gateway token/password)";
|
||||||
|
case "tailscale_proxy_missing":
|
||||||
|
return "unauthorized: tailscale proxy headers missing (use Tailscale Serve or gateway token/password)";
|
||||||
|
case "tailscale_whois_failed":
|
||||||
|
return "unauthorized: tailscale identity check failed (use Tailscale Serve auth or gateway token/password)";
|
||||||
|
case "tailscale_user_mismatch":
|
||||||
|
return "unauthorized: tailscale identity mismatch (use Tailscale Serve auth or gateway token/password)";
|
||||||
|
case "rate_limited":
|
||||||
|
return "unauthorized: too many failed authentication attempts (retry later)";
|
||||||
|
case "device_token_mismatch":
|
||||||
|
return "unauthorized: device token mismatch (rotate/reissue device token)";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authMode === "token" && authProvided === "none") {
|
||||||
|
return `unauthorized: gateway token missing (${tokenHint})`;
|
||||||
|
}
|
||||||
|
if (authMode === "password" && authProvided === "none") {
|
||||||
|
return `unauthorized: gateway password missing (${passwordHint})`;
|
||||||
|
}
|
||||||
|
return "unauthorized";
|
||||||
|
}
|
||||||
@@ -58,87 +58,16 @@ import {
|
|||||||
incrementPresenceVersion,
|
incrementPresenceVersion,
|
||||||
refreshGatewayHealthSnapshot,
|
refreshGatewayHealthSnapshot,
|
||||||
} from "../health-state.js";
|
} from "../health-state.js";
|
||||||
|
import {
|
||||||
|
formatGatewayAuthFailureMessage,
|
||||||
|
resolveHostName,
|
||||||
|
type AuthProvidedKind,
|
||||||
|
} from "./auth-messages.js";
|
||||||
|
|
||||||
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
|
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;
|
||||||
|
|
||||||
const DEVICE_SIGNATURE_SKEW_MS = 10 * 60 * 1000;
|
const DEVICE_SIGNATURE_SKEW_MS = 10 * 60 * 1000;
|
||||||
|
|
||||||
function resolveHostName(hostHeader?: string): string {
|
|
||||||
const host = (hostHeader ?? "").trim().toLowerCase();
|
|
||||||
if (!host) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (host.startsWith("[")) {
|
|
||||||
const end = host.indexOf("]");
|
|
||||||
if (end !== -1) {
|
|
||||||
return host.slice(1, end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const [name] = host.split(":");
|
|
||||||
return name ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthProvidedKind = "token" | "password" | "none";
|
|
||||||
|
|
||||||
function formatGatewayAuthFailureMessage(params: {
|
|
||||||
authMode: ResolvedGatewayAuth["mode"];
|
|
||||||
authProvided: AuthProvidedKind;
|
|
||||||
reason?: string;
|
|
||||||
client?: { id?: string | null; mode?: string | null };
|
|
||||||
}): string {
|
|
||||||
const { authMode, authProvided, reason, client } = params;
|
|
||||||
const isCli = isGatewayCliClient(client);
|
|
||||||
const isControlUi = client?.id === GATEWAY_CLIENT_IDS.CONTROL_UI;
|
|
||||||
const isWebchat = isWebchatClient(client);
|
|
||||||
const uiHint = "open the dashboard URL and paste the token in Control UI settings";
|
|
||||||
const tokenHint = isCli
|
|
||||||
? "set gateway.remote.token to match gateway.auth.token"
|
|
||||||
: isControlUi || isWebchat
|
|
||||||
? uiHint
|
|
||||||
: "provide gateway auth token";
|
|
||||||
const passwordHint = isCli
|
|
||||||
? "set gateway.remote.password to match gateway.auth.password"
|
|
||||||
: isControlUi || isWebchat
|
|
||||||
? "enter the password in Control UI settings"
|
|
||||||
: "provide gateway auth password";
|
|
||||||
switch (reason) {
|
|
||||||
case "token_missing":
|
|
||||||
return `unauthorized: gateway token missing (${tokenHint})`;
|
|
||||||
case "token_mismatch":
|
|
||||||
return `unauthorized: gateway token mismatch (${tokenHint})`;
|
|
||||||
case "token_missing_config":
|
|
||||||
return "unauthorized: gateway token not configured on gateway (set gateway.auth.token)";
|
|
||||||
case "password_missing":
|
|
||||||
return `unauthorized: gateway password missing (${passwordHint})`;
|
|
||||||
case "password_mismatch":
|
|
||||||
return `unauthorized: gateway password mismatch (${passwordHint})`;
|
|
||||||
case "password_missing_config":
|
|
||||||
return "unauthorized: gateway password not configured on gateway (set gateway.auth.password)";
|
|
||||||
case "tailscale_user_missing":
|
|
||||||
return "unauthorized: tailscale identity missing (use Tailscale Serve auth or gateway token/password)";
|
|
||||||
case "tailscale_proxy_missing":
|
|
||||||
return "unauthorized: tailscale proxy headers missing (use Tailscale Serve or gateway token/password)";
|
|
||||||
case "tailscale_whois_failed":
|
|
||||||
return "unauthorized: tailscale identity check failed (use Tailscale Serve auth or gateway token/password)";
|
|
||||||
case "tailscale_user_mismatch":
|
|
||||||
return "unauthorized: tailscale identity mismatch (use Tailscale Serve auth or gateway token/password)";
|
|
||||||
case "rate_limited":
|
|
||||||
return "unauthorized: too many failed authentication attempts (retry later)";
|
|
||||||
case "device_token_mismatch":
|
|
||||||
return "unauthorized: device token mismatch (rotate/reissue device token)";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authMode === "token" && authProvided === "none") {
|
|
||||||
return `unauthorized: gateway token missing (${tokenHint})`;
|
|
||||||
}
|
|
||||||
if (authMode === "password" && authProvided === "none") {
|
|
||||||
return `unauthorized: gateway password missing (${passwordHint})`;
|
|
||||||
}
|
|
||||||
return "unauthorized";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function attachGatewayWsMessageHandler(params: {
|
export function attachGatewayWsMessageHandler(params: {
|
||||||
socket: WebSocket;
|
socket: WebSocket;
|
||||||
upgradeReq: IncomingMessage;
|
upgradeReq: IncomingMessage;
|
||||||
|
|||||||
Reference in New Issue
Block a user