mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
fix: preserve hello-ok scopes for reused device tokens (#68039)
This commit is contained in:
@@ -270,6 +270,69 @@ export function registerDefaultAuthTokenSuite(): void {
|
||||
}
|
||||
});
|
||||
|
||||
test("hello-ok reports persisted token scopes when reusing an existing device token", async () => {
|
||||
const { randomUUID } = await import("node:crypto");
|
||||
const os = await import("node:os");
|
||||
const path = await import("node:path");
|
||||
const token = resolveGatewayTokenOrEnv();
|
||||
const deviceIdentityPath = path.join(
|
||||
os.tmpdir(),
|
||||
`openclaw-shared-auth-scope-reuse-${randomUUID()}.json`,
|
||||
);
|
||||
const wsInitial = await openWs(port);
|
||||
let pairedDeviceToken: string | undefined;
|
||||
let pairedDeviceScopes: unknown;
|
||||
try {
|
||||
const initial = await connectReq(wsInitial, {
|
||||
token,
|
||||
scopes: ["operator.admin"],
|
||||
deviceIdentityPath,
|
||||
});
|
||||
expect(initial.ok).toBe(true);
|
||||
const helloOk = initial.payload as
|
||||
| {
|
||||
auth?: {
|
||||
role?: unknown;
|
||||
scopes?: unknown;
|
||||
deviceToken?: unknown;
|
||||
};
|
||||
}
|
||||
| undefined;
|
||||
expect(helloOk?.auth?.role).toBe("operator");
|
||||
expect(Array.isArray(helloOk?.auth?.scopes)).toBe(true);
|
||||
expect(typeof helloOk?.auth?.deviceToken).toBe("string");
|
||||
pairedDeviceToken = helloOk?.auth?.deviceToken as string | undefined;
|
||||
pairedDeviceScopes = helloOk?.auth?.scopes;
|
||||
} finally {
|
||||
wsInitial.close();
|
||||
}
|
||||
|
||||
const wsReconnect = await openWs(port);
|
||||
try {
|
||||
const reconnect = await connectReq(wsReconnect, {
|
||||
token,
|
||||
scopes: ["operator.read"],
|
||||
deviceIdentityPath,
|
||||
});
|
||||
expect(reconnect.ok).toBe(true);
|
||||
const helloOk = reconnect.payload as
|
||||
| {
|
||||
auth?: {
|
||||
role?: unknown;
|
||||
scopes?: unknown;
|
||||
deviceToken?: unknown;
|
||||
};
|
||||
}
|
||||
| undefined;
|
||||
expect(helloOk?.auth?.role).toBe("operator");
|
||||
expect(helloOk?.auth?.deviceToken).toBe(pairedDeviceToken);
|
||||
expect(helloOk?.auth?.scopes).toEqual(pairedDeviceScopes);
|
||||
expect(helloOk?.auth?.scopes).not.toEqual(["operator.read"]);
|
||||
} finally {
|
||||
wsReconnect.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("does not grant admin when scopes are omitted", async () => {
|
||||
const ws = await openWs(port);
|
||||
const token = resolveGatewayTokenOrEnv();
|
||||
|
||||
@@ -1217,6 +1217,7 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
canvasHostUrl && canvasCapability
|
||||
? (buildCanvasScopedHostUrl(canvasHostUrl, canvasCapability) ?? canvasHostUrl)
|
||||
: canvasHostUrl;
|
||||
const helloOkAuthScopes = deviceToken ? deviceToken.scopes : scopes;
|
||||
const helloOk = {
|
||||
type: "hello-ok",
|
||||
protocol: PROTOCOL_VERSION,
|
||||
@@ -1229,7 +1230,7 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
canvasHostUrl: scopedCanvasHostUrl,
|
||||
auth: {
|
||||
role,
|
||||
scopes,
|
||||
scopes: helloOkAuthScopes,
|
||||
...(deviceToken
|
||||
? {
|
||||
deviceToken: deviceToken.token,
|
||||
|
||||
Reference in New Issue
Block a user