The short of it is that your game design and art both need to be built around the realities of networked play.
When the user clicks, they should not immediately attack. Instead, the animation/effects should be a "pre-attack" visual that can be smoothly transitioned into a full attack animation/effect or a canceled effect. More over, this pre-attack should be of indefinite length; this allows the request to smoothly cover up any of the unpredictable network latencies.
Once this pre-attack animation is started, the client just waits for the server's authoritative notification that the attack has started or failed. The server should also allow some graceful flexibility in timings to account for expected inaccuracies, e.g. if the client's attack request comes in a few ticks before the timer expires then the server can just enque the attack and have it fire when the timer fully expires. From the client's perspective, this delay is no different than any other network latency.
Once the client receives the server confirmation, it can transition into the proper attack animation. The other clients likewise play the attack. The server indicates the time that the attack should have started; using this and the client's estimated latency, the clients can compress or lengthen the pre-attack/transition animation so that all the clients play the actual attack animation at roughly the same time that the attack happens on the server.
If the server sends back a MSG_ID_NO_WAY_JOSE
message then you can instead transition from the pre-attack animation to an attack failed animation of some kind (using whatever in-game fiction you want to illustrate the failure). Using the above tricks, though, these failures should be extremely rare (to the point that they are probably only happening on clients with very low framerates or which have been hacked in an attempt to subvert cooldowns).
A lot of this also somewhat depends on the style of game. What is going to work best in an FPS is not the same as what works best in an RTS, for instance. Something at the pace of a typical MMORPG should work with what I've outlined above.
Exanple: client A presses the Lazer Beam Attack button. The game is dsigned for laser beam to have a ~0.4s warmup animation. Every client currently has a server latency of ~0.1s. The client sends the attack request to the server at t=0. The server receives it at t=0.1. The server confirms the attack and tells all the clients that client A started the attack at t=0 and the attack will go off at t=0.4. Client A receives this at t=0.2 so it knows that it has 0.2s left of the warmup animation to play. The other clients likewise just found out about the attack, so they know to play 0.2s of warmup animation for player A's avatar and then to play the attack animation.
Example 2: client A presses the Lazer Beam Attack button but due to client performance its timing is off and the client allows the player to press the button early. The server receives the request at t=0.1 and rejects it. The client receives the rejection at t=0.2, so the warmup animation has already been playing for 1/5th of a second. The client then transitions to a failure animation. None of the other clients ever know that anything happened.
Example 3: client A presses the Lazer Beam Attack button a hair earlier than allowed because of minute timing differences. The client sends the request at t=0 and the server receives it at t=0.1. The server knows that the client isn't allowed to attack until t=0.2. It waits until then and then tells all the clients that client A is attacking; the server offsets the time from the allowed time, not the received time, so it tells all clients that client A attacked at t=0.1 and the attack will go off at t=0.5. Client A receives this at t=0.3 and knows that it needs to length the warmup animation out a bit longer to t=0.5 (the animation normally takes 0.4s but in this case it needs to be slowed/extended to take a total of 0.5s). The other clients instead play the shortened warmup animation (because they only found out about it at t=0.3 and will do the full attack at t=0.5, for a duration of only 0.2s).
Note: these are not the only ways to solve these problems. There are other potential solutions, but they all involve some level of game design consideration and some amount of art support.
In short: you can't possibly force the client and server to be in sync, but you can use game design and art to hide the network latencies incurred by server-authoritative play.
t = (t_clientRecievedReply + t_clientSent)/2
and adjust the cooldown time accordingly. Also maybe allow some commands to be "queued" on the server if the cooldown is close enough to finishing it will automatically execute when the cooldown ends (the message to the client would then have to let it know that the ability was queued so the client can guess the correct time of cooldown). \$\endgroup\$