mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 00:18:26 +00:00
fix(security): harden hook and device token auth
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
getPairedDevice,
|
||||
requestDevicePairing,
|
||||
rotateDeviceToken,
|
||||
verifyDeviceToken,
|
||||
} from "./device-pairing.js";
|
||||
|
||||
describe("device pairing tokens", () => {
|
||||
@@ -41,4 +42,40 @@ describe("device pairing tokens", () => {
|
||||
paired = await getPairedDevice("device-1", baseDir);
|
||||
expect(paired?.tokens?.operator?.scopes).toEqual(["operator.read"]);
|
||||
});
|
||||
|
||||
test("verifies token and rejects mismatches", async () => {
|
||||
const baseDir = await mkdtemp(join(tmpdir(), "openclaw-device-pairing-"));
|
||||
const request = await requestDevicePairing(
|
||||
{
|
||||
deviceId: "device-1",
|
||||
publicKey: "public-key-1",
|
||||
role: "operator",
|
||||
scopes: ["operator.read"],
|
||||
},
|
||||
baseDir,
|
||||
);
|
||||
await approveDevicePairing(request.request.requestId, baseDir);
|
||||
const paired = await getPairedDevice("device-1", baseDir);
|
||||
const token = paired?.tokens?.operator?.token;
|
||||
expect(token).toBeTruthy();
|
||||
|
||||
const ok = await verifyDeviceToken({
|
||||
deviceId: "device-1",
|
||||
token: token ?? "",
|
||||
role: "operator",
|
||||
scopes: ["operator.read"],
|
||||
baseDir,
|
||||
});
|
||||
expect(ok.ok).toBe(true);
|
||||
|
||||
const mismatch = await verifyDeviceToken({
|
||||
deviceId: "device-1",
|
||||
token: "x".repeat((token ?? "1234").length),
|
||||
role: "operator",
|
||||
scopes: ["operator.read"],
|
||||
baseDir,
|
||||
});
|
||||
expect(mismatch.ok).toBe(false);
|
||||
expect(mismatch.reason).toBe("token-mismatch");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { safeEqualSecret } from "../security/secret-equal.js";
|
||||
|
||||
export type DevicePairingPendingRequest = {
|
||||
requestId: string;
|
||||
@@ -431,7 +432,7 @@ export async function verifyDeviceToken(params: {
|
||||
if (entry.revokedAtMs) {
|
||||
return { ok: false, reason: "token-revoked" };
|
||||
}
|
||||
if (entry.token !== params.token) {
|
||||
if (!safeEqualSecret(params.token, entry.token)) {
|
||||
return { ok: false, reason: "token-mismatch" };
|
||||
}
|
||||
const requestedScopes = normalizeScopes(params.scopes);
|
||||
|
||||
Reference in New Issue
Block a user