While I think that there will never be a 100% solution, imho, it depends on the kind of game you are making. IIRC, you want to create a FPS, so here's some ideas I'd put in there in no particular order. I am not a professional game dev, though, so others might come up with better ideas.
Run the game simulation on the server, too , and check if inputs sent by the client are plausible. For example, make sure a player can only move a certain distance in a certain time. I'd use a path-finding algorithm against a wall-map just to make sure and get the path length between the prior and the next position. You can check things like turn-speed and, too, and check that against hit-precision. Also make sure trivial physics apply, for example players should not be able to float around...
Send the least info possible. Using above technique, you can only send other players' data to a client which are visible by a player. That way, many hacks will be useless or deliver sub-optimal results.
Send a screenshot from the canvas to the server and let the server render the very same frame. Analyze and compare them in order to find tampering (like see-through walls). The client might render slightly different because of floating-point inaccuracies, so it's not as easy as comparing every pixel!
Use a heartbeat in order to detect debugging breakpoints. If two consecutive heartbeats take a long time, a player probably debugged your code, so you should at least flag them for tampering. Service workers might help with catching network problems, though...
Don't immediately kick/ban cheaters once you find out they cheat, because that would tell them precisely how you check for cheating on your server. They might create a new account and check for different things, then make sure to write a hack which cannot be recognized by the server. Instead ban them after some time, so that they cannot be sure what triggered the anti-cheat.
Check in-game time and precision. Bots might run for many hours straight, delivering stable performance. Even if the hit-chance is randomized, they will probably still have a very high hit-likelihood. If a player can achieve a certain kind of kill-likelihood and keep it constant for 10+ hours straight, you know something is fishy. Humans fluctuate in performance, have to go to the toilet or eat/drink something. It's detectable, however you'll need to collect some data about your players.
Observe laggy players, because high ping rates might be falsified in order to get an edge over other players. If a player with a high ping has a high hit-rate, there might be something wrong.
Check hit locations. Usually, a human will try to hit what they see first, aiming for high-damage parts first. Humans are not perfect, so the hit location will differ. An aim-bot, for example, will always hit a similar spot, so that might be an indicator for cheating.
Also, while I never gave them a try, there are professional services, like jscrambler. Maybe see if they work for you if you have money to spend...
Unbezahlte Werbung durch Nennung und Verlinkung von Personen, Organisationen oder Unternehmen.