1

I have a simple single page application (a game) written in Vue.js with a backend in Node.js, all hosted on Heroku. My frontend in Vue uses axios to do the api call to my backend, which uses express and mysql libraries to query my database and get high scores or post a new score.

I gave the finished game to my friends and they realized right away they could use postman or similar to do a simple post request and send a fake score, so I'd like to secure it.

I'm open to anything fairly simple, but I'd like to set a token that I can check in my Node.js if it matches, and if not, send a 403. I've tried setting an environment variable with a token, but on the front end ends up displaying that token in the resources if I inspect the element (if I use a .env file and then get the value). I've also tried my config.json files, but obviously there's no way to hide these values from anyone using inspect element. I tried checking the req.hostname but even when I send a request from postman, it returns a 200.

How can I secure my post request?

dattebane
  • 219
  • 2
  • 9
  • 1
    You cannot secure the POST request, anyone might send any request to your server. It's impossible to secure the clientside code as well, so you cannot hide a token there. The only viable way to really secure your highscore is to put (the important parts of) the game logic on the server side, so that you can compute or at least validate the score there. – Bergi Aug 18 '19 at 20:23
  • Possible duplicate of this [question](https://stackoverflow.com/questions/4733175/safest-way-to-update-game-score-from-client-to-server-database-javascript). – Andrew Vasylchuk Aug 18 '19 at 20:45

1 Answers1

1

Problem

As others have pointed out, there is no generic way to generate information client side that cannot be forged. The problem being that no matter how complex the rules to generate this information (e.g. game scores must be prime numbers), somebody might isolate those rules and create arbitrary information (e.g. fake prime number scores without playing the game).

For games this often leads to input processing (client) and game rules (server) being split between client & server, making it impossible to isolate score generation from game rules. However this introduces latency and asynchronicity and requires heavy refactoring for client side games - three difficult issues.

Solution

There are scenarios where a different solution exists. Take chess: given a chessboard ask the client for the least possible number of moves until mate. The number of moves is the score and the lowest score wins. The client must send the specific moves and the server verifies the result. In other words the client side information is the entire input the player generates for the game.

As generic pattern this means: define the client side (score) information as entire game input. Record the entire input client side and re-run the game server side with this input. Verify the result.

Requirements:

  • Split input processing from game rules so that it can run with pre-defined input.
  • Implement equivalent server and client side game rules.
  • Eliminate any source of randomness! (E.g. use the same seed for the same random number generator or a server generated random number list)

You are close to this solution as you have wisely chosen one language for server and client, and Javascript represents numbers as plattform independent 64-bit floats (which avoids rounding errors). This solution avoids latency & asynchronicity, but does not allow multi-player games where atomic server side updates and coupled player input is needed.

B M
  • 3,893
  • 3
  • 33
  • 47