Do you have a “game board” actor blueprint? Set it to replicate and then replicate whatever variables on that blueprint need to stay in sync. Alternately, I think the GameState would be a good place to keep that information, but if you have a game board actor already, why not use that?
Your GameState could have a variable to keep track of whose turn it is and only accept PlayerController commands from the correct PlayerController. Run all input commands on the server and then multicast the outcomes to the client(s).