validate persistent id to prevent player spoofing

This commit is contained in:
Evan
2025-02-18 13:53:28 -08:00
parent 4f3ad5c1ac
commit 876fb8dbf9
3 changed files with 17 additions and 5 deletions
+3 -4
View File
@@ -26,10 +26,6 @@ import {
} from "../core/Schemas";
import { LobbyConfig } from "./ClientGameRunner";
import { LocalServer } from "./LocalServer";
import { UsernameInput } from "./UsernameInput";
import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
import { SinglePlayerModal } from "./SinglePlayerModal";
import { PlayerView } from "../core/game/GameView";
export class PauseGameEvent implements GameEvent {
@@ -175,6 +171,7 @@ export class Transport {
ClientPingMessageSchema.parse({
type: "ping",
clientID: this.lobbyConfig.clientID,
persistentID: this.lobbyConfig.persistentID,
gameID: this.lobbyConfig.gameID,
}),
),
@@ -437,6 +434,7 @@ export class Transport {
const msg = ClientSendWinnerSchema.parse({
type: "winner",
clientID: this.lobbyConfig.clientID,
persistentID: this.lobbyConfig.persistentID,
gameID: this.lobbyConfig.gameID,
winner: event.winner,
});
@@ -455,6 +453,7 @@ export class Transport {
const msg = ClientIntentMessageSchema.parse({
type: "intent",
clientID: this.lobbyConfig.clientID,
persistentID: this.lobbyConfig.persistentID,
gameID: this.lobbyConfig.gameID,
intent: intent,
});
+1 -1
View File
@@ -267,6 +267,7 @@ export const ServerMessageSchema = z.union([
const ClientBaseMessageSchema = z.object({
type: z.enum(["winner", "join", "intent", "ping", "log"]),
clientID: ID,
persistentID: SafeString.nullable(), // WARNING: persistent id is private.
gameID: ID,
});
@@ -294,7 +295,6 @@ export const ClientIntentMessageSchema = ClientBaseMessageSchema.extend({
// WARNING: never send this message to clients.
export const ClientJoinMessageSchema = ClientBaseMessageSchema.extend({
type: z.literal("join"),
persistentID: SafeString, // WARNING: persistent id is private.
lastTurn: z.number(), // The last turn the client saw.
username: SafeString,
});
+13
View File
@@ -103,6 +103,19 @@ export class GameServer {
const clientMsg: ClientMessage = ClientMessageSchema.parse(
JSON.parse(message),
);
if (this.allClients.has(clientMsg.clientID)) {
const client = this.allClients.get(clientMsg.clientID);
if (client.persistentID != clientMsg.persistentID) {
console.warn(
`Client ID ${clientMsg.clientID} sent incorrect id ${clientMsg.persistentID}, does not match persistent id ${client.persistentID}`,
);
return;
}
}
// Clear out persistent id to make sure it doesn't get sent to other clients.
clientMsg.persistentID = null;
if (clientMsg.type == "intent") {
if (clientMsg.gameID == this.id) {
this.addIntent(clientMsg.intent);