How to Check Authenticity of an AJAX Request How to Check Authenticity of an AJAX Request ajax ajax

How to Check Authenticity of an AJAX Request


You can't guarantee the security of the timings cryptographically, because the client's browser can't do secure computation. Any means for encrypting to/from the server could be bypassed by adjusting the actual timings.

And timing on the server doesn't work, either - if you don't take account of latency in the round-trip-time, users with lower latency connections will have an advantage; if you do, users could thwart the compensation phase by adding extra latency there and then removing it later.

You can, of course make it difficult for the users to modify this, but security by obscurity is an unsustainable policy anyway.

So it comes down to either trusting your users somewhat (a reasonable assumption, most of the time) and designing the game so it's not trivial to circumvent the timings.


This approach obviously makes assumptions and is not invincible. All calculations are done on the client, and the server does some background checks to find out if the request could have been forged. Like any other client-based approach, this is not deterministic but makes it very hard for a lying client.

The main assumption is that long-lived HTTP connections are much faster for transmitting data, even negligible in some cases depending on the application context. It is used in most online trading systems as stock prices can change multiple times within a second, and this is the fastest way to transmit current price to users. You can read up more about HTTP Streaming or Comet here.

Start by creating a full-duplex ajax connection between the client and server. The server has a dedicated line to talk to the client, and the client can obviously talk to the server. The server sends the puzzle, and other messages to the client on this dedicated line. The client is supposed to confirm the receipt of each message to the server along with its local timestamp.

On the server generate random tokens (could be just distinct integers) after the puzzle has been sent, record the time when each token was generated, and pass it over to the client. The client sees the message, and is supposed to immediately relay this token back along with it's local time of receipt. To make it unpredictable for the client, generate these server tokens at random intervals, say between 1 and n ms.

There would be three types of messages that the client sends to the server:

PUZZLE_RECEIVEDTOKEN_RECEIVEDPUZZLE_COMPLETED

And two types of messages that the server sends to the client:

PUZZLE_SENTTOKEN_SENT

There could be a lot of time variation in the messages send from the client to the server, but much lesser in the other direction (and that's a very fair assumption, hey - we have to start somewhere).

Now when the server receives a receipt to a message it sent, record the client time contained in that message. Since the token was also relayed back in this message, we can match it with the corresponding token on the server. At the end of the puzzle, the client sends a PUZZLE_COMPLETED message with local time to the server. The time to complete the puzzle would be:

PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time

Then double check by calculating the time difference in each message's sent vs received times.

PUZZLE_RECEIVED.time - PUZZLE_SENT.timeTOKEN_RECEIVED.time - TOKEN_SENT.time

A high variance in these times implies that the response could have been forged. Besides simple variance, there is lots of statistical analysis you can do on this data to look for odd patterns.


Even a compiled application could be forged. If the user changes their system clock halfway through timing, your application will report an incorrect time to the server. The only way to get an accurate upper-bound on the time it takes them is to start timing on the server when the puzzle is given to them, and to stop timing when they supply the answer.

As others have pointed out you can minimise the effect that slow connections have by making the load of the puzzle as small as possible. Load the entire page and "game engine" first, and then use an asynchronous request to load the puzzle itself (which should be a small amount of data) to level the playing field as much as possible.

Unfortunately you can't do latency compensation as this would be open to tampering. However, on a connection that's not being used for anything else, the latency for a request like this would be greatly overshadowed by the time it takes a human to solve a puzzle, I don't think it will be a big deal.

(Reasoning: 200ms is considered very bad lag, and that's the average human reaction time. The shortest possible "puzzle" for a human to complete would be a visual reaction speed test, in which case bad lag would have a 100% markup on their results. So as a timing solution this is 2-OPT. Any puzzle more complex will be impacted less by lag.)

I would also put a banner on the page saying to not use the internet connection for anything else while playing for the best possible speeds, possibly linking to a speed / latency tester.