diff --git a/package-lock.json b/package-lock.json index 825b7e4153e9548048930504c3b46a0856f3d2bc..519c08389b35057159711a64cdf76c1337899ffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4316,6 +4316,11 @@ "randomfill": "^1.0.3" } }, + "crypto-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", diff --git a/package.json b/package.json index 529a9a8761eacc1995254bea7984b1b356e395a5..b1e1bec8b9ba25340747dffe550885d547f4af18 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@rooks/use-window-size": "^4.5.0", "@sentry/react": "^5.23.0", "classnames": "^2.2.6", + "crypto-js": "^4.0.0", "date-fns": "^2.16.1", "immer": "^7.0.15", "keycloak-js": "^10.0.2", diff --git a/src/actions/users.js b/src/actions/users.js index 49cf58bb99164c92d36367dbadd39648c2d35bf9..3f5f5ef55d92fd48c4aecdf4dfd7eee28398405a 100644 --- a/src/actions/users.js +++ b/src/actions/users.js @@ -27,6 +27,7 @@ export const loadMe = createAsyncAction( state.user.id = result.payload.id; state.user.group = result.payload.group; state.user.isBanned = result.payload.is_banned; + state.user.secret = result.payload.secret || ""; } }); } diff --git a/src/ws/connection.js b/src/ws/connection.js index 4882d1b5ef831c535322d4f8a46e0bdd992ad09b..19ced7f0d14ba7b86c43b11eec7da2b236cd1bab 100644 --- a/src/ws/connection.js +++ b/src/ws/connection.js @@ -1,6 +1,8 @@ +import hex from "crypto-js/enc-hex"; +import hmacSHA1 from "crypto-js/hmac-sha1"; import WaitQueue from "wait-queue"; -import { GlobalInfoStore } from "stores"; +import { AuthStore, GlobalInfoStore } from "stores"; import { handlers } from "./handlers"; @@ -44,6 +46,18 @@ function Worker() { }; } +const buildKeepalivePayload = async () => { + const { user } = AuthStore.getRawState(); + const payload = user && user.id ? user.id.toString() : ""; + const signature = user.secret ? hmacSHA1(payload, user.secret) : null; + + return { + event: "KEEPALIVE", + payload, + sig: hex.stringify(signature), + }; +}; + export const connect = ({ onConnect }) => { return new Promise((resolve, reject) => { const worker = Worker(); @@ -61,14 +75,17 @@ export const connect = ({ onConnect }) => { state.connectionState = "connected"; }); console.log("[ws] Connected."); - ws.send("CONNECT"); - keepAliveInterval = setInterval(() => { - ws.send("KEEPALIVE"); + const sendKeepalive = async () => { + ws.send(JSON.stringify(await buildKeepalivePayload())); console.debug("[ws] Sending keepalive."); - }, 30 * 1000); + }; + + sendKeepalive(); + + keepAliveInterval = setInterval(sendKeepalive, 15 * 1000); - const self = { ws, worker }; + const self = { ws, worker, sendKeepalive }; if (onConnect) { return onConnect(self).then(() => resolve(self)); diff --git a/typings/cf2021.d.ts b/typings/cf2021.d.ts index fa510f244c8899b72ccb2c54cca831ba32e4eb8c..4b9d6284b1f7a44f79bb0707050d50cbbae745f6 100644 --- a/typings/cf2021.d.ts +++ b/typings/cf2021.d.ts @@ -46,6 +46,7 @@ declare namespace CF2021 { id?: number; isBanned?: boolean; group?: string; + secret?: string; }; }