mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:11:35 +00:00
test: optimize auth and audit test runtime
This commit is contained in:
@@ -296,14 +296,14 @@ describe("gateway server auth/connect", () => {
|
||||
await server.close();
|
||||
});
|
||||
|
||||
test("closes silent handshakes after timeout", { timeout: 60_000 }, async () => {
|
||||
test("closes silent handshakes after timeout", async () => {
|
||||
vi.useRealTimers();
|
||||
const prevHandshakeTimeout = process.env.OPENCLAW_TEST_HANDSHAKE_TIMEOUT_MS;
|
||||
process.env.OPENCLAW_TEST_HANDSHAKE_TIMEOUT_MS = "50";
|
||||
process.env.OPENCLAW_TEST_HANDSHAKE_TIMEOUT_MS = "20";
|
||||
try {
|
||||
const ws = await openWs(port);
|
||||
const handshakeTimeoutMs = getHandshakeTimeoutMs();
|
||||
const closed = await waitForWsClose(ws, handshakeTimeoutMs + 250);
|
||||
const closed = await waitForWsClose(ws, handshakeTimeoutMs + 120);
|
||||
expect(closed).toBe(true);
|
||||
} finally {
|
||||
if (prevHandshakeTimeout === undefined) {
|
||||
@@ -567,54 +567,50 @@ describe("gateway server auth/connect", () => {
|
||||
await new Promise<void>((resolve) => ws.once("close", () => resolve()));
|
||||
});
|
||||
|
||||
test(
|
||||
"invalid connect params surface in response and close reason",
|
||||
{ timeout: 60_000 },
|
||||
async () => {
|
||||
const ws = await openWs(port);
|
||||
const closeInfoPromise = new Promise<{ code: number; reason: string }>((resolve) => {
|
||||
ws.once("close", (code, reason) => resolve({ code, reason: reason.toString() }));
|
||||
});
|
||||
test("invalid connect params surface in response and close reason", async () => {
|
||||
const ws = await openWs(port);
|
||||
const closeInfoPromise = new Promise<{ code: number; reason: string }>((resolve) => {
|
||||
ws.once("close", (code, reason) => resolve({ code, reason: reason.toString() }));
|
||||
});
|
||||
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
type: "req",
|
||||
id: "h-bad",
|
||||
method: "connect",
|
||||
params: {
|
||||
minProtocol: PROTOCOL_VERSION,
|
||||
maxProtocol: PROTOCOL_VERSION,
|
||||
client: {
|
||||
id: "bad-client",
|
||||
version: "dev",
|
||||
platform: "web",
|
||||
mode: "webchat",
|
||||
},
|
||||
device: {
|
||||
id: 123,
|
||||
publicKey: "bad",
|
||||
signature: "bad",
|
||||
signedAt: "bad",
|
||||
},
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
type: "req",
|
||||
id: "h-bad",
|
||||
method: "connect",
|
||||
params: {
|
||||
minProtocol: PROTOCOL_VERSION,
|
||||
maxProtocol: PROTOCOL_VERSION,
|
||||
client: {
|
||||
id: "bad-client",
|
||||
version: "dev",
|
||||
platform: "web",
|
||||
mode: "webchat",
|
||||
},
|
||||
}),
|
||||
);
|
||||
device: {
|
||||
id: 123,
|
||||
publicKey: "bad",
|
||||
signature: "bad",
|
||||
signedAt: "bad",
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const res = await onceMessage<{
|
||||
ok: boolean;
|
||||
error?: { message?: string };
|
||||
}>(
|
||||
ws,
|
||||
(o) => (o as { type?: string }).type === "res" && (o as { id?: string }).id === "h-bad",
|
||||
);
|
||||
expect(res.ok).toBe(false);
|
||||
expect(String(res.error?.message ?? "")).toContain("invalid connect params");
|
||||
const res = await onceMessage<{
|
||||
ok: boolean;
|
||||
error?: { message?: string };
|
||||
}>(
|
||||
ws,
|
||||
(o) => (o as { type?: string }).type === "res" && (o as { id?: string }).id === "h-bad",
|
||||
);
|
||||
expect(res.ok).toBe(false);
|
||||
expect(String(res.error?.message ?? "")).toContain("invalid connect params");
|
||||
|
||||
const closeInfo = await closeInfoPromise;
|
||||
expect(closeInfo.code).toBe(1008);
|
||||
expect(closeInfo.reason).toContain("invalid connect params");
|
||||
},
|
||||
);
|
||||
const closeInfo = await closeInfoPromise;
|
||||
expect(closeInfo.code).toBe(1008);
|
||||
expect(closeInfo.reason).toContain("invalid connect params");
|
||||
});
|
||||
});
|
||||
|
||||
describe("password auth", () => {
|
||||
@@ -932,97 +928,85 @@ describe("gateway server auth/connect", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("accepts device token auth for paired device", async () => {
|
||||
test("device token auth matrix", async () => {
|
||||
const { server, ws, port, prevToken } = await startServerWithClient("secret");
|
||||
const { deviceToken } = await ensurePairedDeviceTokenForCurrentIdentity(ws);
|
||||
|
||||
ws.close();
|
||||
|
||||
const ws2 = await openWs(port);
|
||||
const res2 = await connectReq(ws2, { token: deviceToken });
|
||||
expect(res2.ok).toBe(true);
|
||||
const scenarios: Array<{
|
||||
name: string;
|
||||
opts: Parameters<typeof connectReq>[1];
|
||||
assert: (res: Awaited<ReturnType<typeof connectReq>>) => void;
|
||||
}> = [
|
||||
{
|
||||
name: "accepts device token auth for paired device",
|
||||
opts: { token: deviceToken },
|
||||
assert: (res) => {
|
||||
expect(res.ok).toBe(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepts explicit auth.deviceToken when shared token is omitted",
|
||||
opts: {
|
||||
skipDefaultAuth: true,
|
||||
deviceToken,
|
||||
},
|
||||
assert: (res) => {
|
||||
expect(res.ok).toBe(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "uses explicit auth.deviceToken fallback when shared token is wrong",
|
||||
opts: {
|
||||
token: "wrong",
|
||||
deviceToken,
|
||||
},
|
||||
assert: (res) => {
|
||||
expect(res.ok).toBe(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keeps shared token mismatch reason when fallback device-token check fails",
|
||||
opts: { token: "wrong" },
|
||||
assert: (res) => {
|
||||
expect(res.ok).toBe(false);
|
||||
expect(res.error?.message ?? "").toContain("gateway token mismatch");
|
||||
expect(res.error?.message ?? "").not.toContain("device token mismatch");
|
||||
expect((res.error?.details as { code?: string } | undefined)?.code).toBe(
|
||||
ConnectErrorDetailCodes.AUTH_TOKEN_MISMATCH,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reports device token mismatch when explicit auth.deviceToken is wrong",
|
||||
opts: {
|
||||
skipDefaultAuth: true,
|
||||
deviceToken: "not-a-valid-device-token",
|
||||
},
|
||||
assert: (res) => {
|
||||
expect(res.ok).toBe(false);
|
||||
expect(res.error?.message ?? "").toContain("device token mismatch");
|
||||
expect((res.error?.details as { code?: string } | undefined)?.code).toBe(
|
||||
ConnectErrorDetailCodes.AUTH_DEVICE_TOKEN_MISMATCH,
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
ws2.close();
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
});
|
||||
|
||||
test("accepts explicit auth.deviceToken when shared token is omitted", async () => {
|
||||
const { server, ws, port, prevToken } = await startServerWithClient("secret");
|
||||
const { deviceToken } = await ensurePairedDeviceTokenForCurrentIdentity(ws);
|
||||
|
||||
ws.close();
|
||||
|
||||
const ws2 = await openWs(port);
|
||||
const res2 = await connectReq(ws2, {
|
||||
skipDefaultAuth: true,
|
||||
deviceToken,
|
||||
});
|
||||
expect(res2.ok).toBe(true);
|
||||
|
||||
ws2.close();
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
});
|
||||
|
||||
test("uses explicit auth.deviceToken fallback when shared token is wrong", async () => {
|
||||
const { server, ws, port, prevToken } = await startServerWithClient("secret");
|
||||
const { deviceToken } = await ensurePairedDeviceTokenForCurrentIdentity(ws);
|
||||
|
||||
ws.close();
|
||||
|
||||
const ws2 = await openWs(port);
|
||||
const res2 = await connectReq(ws2, {
|
||||
token: "wrong",
|
||||
deviceToken,
|
||||
});
|
||||
expect(res2.ok).toBe(true);
|
||||
|
||||
ws2.close();
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
});
|
||||
|
||||
test("keeps shared token mismatch reason when token fallback device-token check fails", async () => {
|
||||
const { server, ws, port, prevToken } = await startServerWithClient("secret");
|
||||
await ensurePairedDeviceTokenForCurrentIdentity(ws);
|
||||
|
||||
ws.close();
|
||||
|
||||
const ws2 = await openWs(port);
|
||||
const res2 = await connectReq(ws2, { token: "wrong" });
|
||||
expect(res2.ok).toBe(false);
|
||||
expect(res2.error?.message ?? "").toContain("gateway token mismatch");
|
||||
expect(res2.error?.message ?? "").not.toContain("device token mismatch");
|
||||
expect((res2.error?.details as { code?: string } | undefined)?.code).toBe(
|
||||
ConnectErrorDetailCodes.AUTH_TOKEN_MISMATCH,
|
||||
);
|
||||
|
||||
ws2.close();
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
});
|
||||
|
||||
test("reports device token mismatch when explicit auth.deviceToken is wrong", async () => {
|
||||
const { server, ws, port, prevToken } = await startServerWithClient("secret");
|
||||
await ensurePairedDeviceTokenForCurrentIdentity(ws);
|
||||
|
||||
ws.close();
|
||||
|
||||
const ws2 = await openWs(port);
|
||||
const res2 = await connectReq(ws2, {
|
||||
skipDefaultAuth: true,
|
||||
deviceToken: "not-a-valid-device-token",
|
||||
});
|
||||
expect(res2.ok).toBe(false);
|
||||
expect(res2.error?.message ?? "").toContain("device token mismatch");
|
||||
expect((res2.error?.details as { code?: string } | undefined)?.code).toBe(
|
||||
ConnectErrorDetailCodes.AUTH_DEVICE_TOKEN_MISMATCH,
|
||||
);
|
||||
|
||||
ws2.close();
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
try {
|
||||
for (const scenario of scenarios) {
|
||||
const ws2 = await openWs(port);
|
||||
try {
|
||||
const res = await connectReq(ws2, scenario.opts);
|
||||
scenario.assert(res);
|
||||
} finally {
|
||||
ws2.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await server.close();
|
||||
restoreGatewayToken(prevToken);
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps shared-secret lockout separate from device-token auth", async () => {
|
||||
|
||||
Reference in New Issue
Block a user