8
\$\begingroup\$

Imagine I have an HTML5 web game where the user can get points by doing certain activities. The game can be played offline, so there's not necessarily a live internet connection (note: this makes this question other than existing questions). Game state will then be synchronized at a later moment.

How can the frontend tell the server that the user has indeed gained those points without giving the user the ability to cheat? E.g. by doing a REST call with a multitude of his points? How can the server tell the difference between a real call and a fake call?

What I can think of is to send not the points, but e.g. all the moves of the game, and then the server recomputes the game and calculates the gained points? But that is quite hard, and the game must be deterministic in order to give the client and server the exact same result from the moves.

Does anybody know how existing games implement this? Or how it could theoretically be done?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I think your idea is not bad. But instead of sending all the moves at the end of the game, send each move as it happens, at let the server compute its effect on the score the player has achieved so far. I guess the only way to really prevent cheating is to do as much as possible server side, and even then you probably can't be 100% certain. \$\endgroup\$
    – Christian
    Aug 16, 2013 at 11:25
  • 1
  • 2
    \$\begingroup\$ @Christian True. For live-games, that works. I didn't explicitly say that at first (edited now though) but the 'problem' is that the game can also be played offline. So there's not always a live internet connection. That's why I would send the game afterwards at once... :-) \$\endgroup\$ Aug 16, 2013 at 20:11

3 Answers 3

9
\$\begingroup\$

You might think it's hard, but the way you came up with is the way to do it:

send not the points, but e.g. all the moves of the game, and then the server recomputes the game and calculates the gained points

(this is just one of a million reasons why developing multiplayer online games is harder than developing single-player games)

\$\endgroup\$
2
  • \$\begingroup\$ Well @jhocking, it is a single-player game really, but with a leaderboard so the scores need to arrive at the server, still... The hard thing is that the game can be played offline, so that the game/moves/score might be sent for several games at once, afterwards. Is there a smart technique to do that for games that have lots of moves/state or should I take the pain of sending these huge amounts of data to the server (maybe only if the user ends in the top 10% of scores)? \$\endgroup\$ Aug 16, 2013 at 20:17
  • \$\begingroup\$ I like this approach, but If you really try to implement it, I doubt you will ever finish the game development and have a playable version \$\endgroup\$
    – evilReiko
    Oct 4, 2017 at 6:01
2
\$\begingroup\$

You really should tell us how this is being constructed as different technologies can have different advantages to your situation. Is it in Flash? PHP? HTML5? JavaSript? Java? The "web" tag doesn't give us much to go off.

That being said:

One of the most secure ways to transmit points score is to not let the client side decide what those points are. What you want is to create points based events:

  • Willem killed a zombie! - Score_KillZombie
  • Willem looted a zombie! - Score_LootZombie
  • Willem became a zombie! - Score_OopsIAmZombie

These could be represented as enums in your client and get transmitted to the server on a per score event basis. You just killed a zombie? Excellent take the zombies ID - apply the killed zombie event and send this packet of info to the server. The server then confirms the actions - keeps tally of the score and confirms this with the client side so it can display it.

The zombie having an ID prevents your players from replicating any ID's they can't send Score_KillZombie on a zombie ID "10000000" that your server knows isn't there or already dead. They can also not reloot a zombie that your server flags as empty of loot.

These situations go on and on but the important thing is that you give your server all the control on what actually is set in the game environment. Your client should simply tell the server what predefined event has happened and the server itself will decide if the client is lying or not (remember - it doesn't always have to listen to a client - that's where it weeds out any cheaters.)

Pretty much any implementation of a web game that relies on interaction with a client-server model does this predefined event driven approach. FPS's tell the server when they have shot and in which direction - the server decides if it actually hit the player. MMO's tell the server who their target it is and what spell they want to cast - the server decides if they have enough mana and are in range to do so, reporting back if the target dies. Even Facebook apps will authenticate actions like in Marvel Avengers, sending a move and the target bad guy, the server will decide how much damage it did and what the bad guy does as a reaction.

In conclusion

Never let the client make any authoritative decisions.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ While I agree with your answer, the technology that's being used really doesn't change anything. If the game runs in a browser, you can see all the network requests by simply activating the debug-console/inspector. And even compiled applications can be decompiled, you can peek into the memory, you can read network traffic with third-party tools etc. \$\endgroup\$
    – bummzack
    Aug 16, 2013 at 17:06
  • \$\begingroup\$ Note that you may need to take this idea even further - for instance, even 'killed zombie ID #n' shouldn't be sent from the client because the user could, e.g., spam a full set of IDs, or more subtly find the IDs of nearby zombies (by snooping game updates) and guarantee successfully killing them. The key takeaway is 'never trust the client for ANYTHING.' \$\endgroup\$ Aug 16, 2013 at 18:43
  • \$\begingroup\$ That pretty much is covered in my principal of "don't let the client authenticate anything" Only so much I can write ^^ but good point \$\endgroup\$ Aug 16, 2013 at 18:57
  • \$\begingroup\$ @Blue thanks! As for tech, it is HTML5 on the client and the server runs Node.js. But that might change much to the question, apart from the fact that the game can be run offline, so that points/actions need to be transferred at a later point. Storing a complete game is sometimes possible (board games) but in a FPS that might seem impossible. Is there anything for that, e.g. working with some sort of hashes or only sending some specific actions or anything really? \$\endgroup\$ Aug 16, 2013 at 20:13
-2
\$\begingroup\$

Two options that I can think of, but neither are really perfect.

Option one is when the user has completed those activities have the game send a request to the server and the server then sends a request back to the game for evidence that the user has indeed completed those activities (i.e.: presence of a certain item in the inventory, a dead something or another with a flag that designates that player x killed it).

Option two is to program the game in an unusual language and use unusual commands (i.e.: make everything do the opposite of what it usually does). However, this will only really give you a headache and slow down determined users.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Not really perfect indeed. In a webgame, anybody can view the source, so the call to the server sending the points can be viewed one way or another. Then, the user can create its own call but with more points. How can the server tell which call is legitimate? \$\endgroup\$ Aug 16, 2013 at 11:18
  • \$\begingroup\$ Option two would sort of work, most users won't try to reverse engineer the source and/or HTTP calls. But it's generally a bad idea, because it would also confuse the game maker. For more information; en.wikipedia.org/wiki/Security_through_obscurity \$\endgroup\$
    – muhuk
    Aug 16, 2013 at 12:15
  • \$\begingroup\$ @jhocking Hey, be nice. I did point out that option two would give the developer a headache. \$\endgroup\$
    – Alex
    Aug 17, 2013 at 14:25

Not the answer you're looking for? Browse other questions tagged .