Hacker News new | ask | show | jobs
by jchw 2053 days ago
If you want a better server-side solution, you could try employing mandatory idempotency tokens in the request payload. The concept is simple: either have the server give the client an idempotency token as part of the page load, or have the client request one at some point, or have it be something that can be generated on the client side (nonce style) and send it with the request. The server can then validate, using some strongly consistent system, that it has not received any requests in a certain window of time with that token. (Or, possibly, react with the existing response.)

This has an additional benefit that even methods like PUT do not: it works no matter how many layers of your stack might have retry behavior (properly or improperly) and enables safe retry even when you can’t be sure if the request went through or not. The primary downside is that it introduces a single point of failure, though you could theoretically shard it by some property of the request such as the session key/user id/IP address. Still desirable if you have something you really don’t want to repeat, like a transaction. (Probably would be wise to also make those multiple stage, but nonetheless.)

Goes without saying you should definitely still mitigate this on the client side by updating the UI state if JavaScript is available.

1 comments

CSRF tokens solve this problem for free
AFAIK typical CSRF token implementations allow for reuse, and unlike an idempotency token necessarily need to be generated by a trusted server. They solve a different problem.