This is a difficult problem.
The gist of it is that the client should never be trusted, the server is the only source of authority. As such the server should always perform validations on a score before it deems it valid.
That is the difficult bit, what is a valid score? That is completely tied to each game and depending on it's logic it might be impossible to determine if a score is fake or not. Even if you can determine if a score is fake, how can you handle a client sending the maximum valid score every time?
Short story, validating a single value sent over a single request is difficult if not impossible.
I guess you could try using web sockets so the client communicates constantly with the server about what it is doing, sending messages each time the score increases. When the game ends the client could send a message saying the game ended and the server can tally the final score.
If a client get's funky and starts sending too many messages to increase it's score, you can determine it is trying to cheat. Sending messages with score amounts you know can not happen in the game? Cheater. Like that there are many things the server could do to spot unusual behavior on a client.
The problem with that approach is that to send a valid highscore you need a stable internet connection, if you don't the server can't make real time validations, so it won't accept any scores. This might be a compromise you are willing to make, you could have two modes, "For fun" which does not perform real time validations and can not save highscores, and "For score", which does all the validations but needs the stable connection.
Maybe there are easier solutions, but can't think of them right now. Good luck!