I would like to bring a more in depth explanation on how do WordPress NONCEs really work. Also, the accepted answer needs to be updated with more accurate information, since now WordPress also takes into consideration the session token when creating the nonce. The link is a long article I wrote with more in depth explanations.
First, the accepted answer doesn't say how the if
works.
so let's dissect it shall we? Note that I'm using the current version of the statement since now it also takes into account the user's session token
$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
the PHP function substr()
will return a part of the string.
Here, the evaluation of wp_hash()
is the string that substr()
will evaluate and return part of. the -12
argument says to count 12 characters from the end of the string ( the result of wp_hash()
's evaluation ), substr
starts from the end because of the minus sign telling it to do so.
Finally, the last argument 10
, says to return 10 characters as the sub string.
So count 12 characters from the end, then return 10, so the last 2 characters are stripped out of the returned result.
If you check a WordPress NONCE, it contains exactly 10 characters.
Another point I would like to clarify is the lifespan of a the WP NONCE.
We should not say that a nonce is valid for 24 hours, since in reality it's alway less. A NONCE is valid for maximum 24 hours, minimum 12 hours. Better said, it is valid for 2 ticks.
A tick, as @Stephen Harris explained, is an increment of the current lifespan of the NONCE.
And by default a tick represents 12 hours calculated from UTC time. So at midnight +1 second and midday +1 second, the tick's value is incremented by 1
unit.
Given that the $token
remains the same (the user did not logout and back in), then wp_hash()
will always return the same hash for a given action and user id.
This will remain true until the current tick value is incremented by 1. In which case, the hash will be different for the same action, same user id and same token.
This is how WordPress considers valid a nonce created 0-12 hours ago.
WordPress also consider valid a nonce created 12-24 hours ago by comparing the nonce with the hash function using the previous tick value. But this is misleading as I already mentioned. The 12-24 hours ago period doesn't refer to the actual explicit creation time of a given NONCE ( in other words it's not using the timestamp of the nonce creation ) but rather says in the period of hours ranging from 12-24 since it's creation. Which actually refers to a unique tick value ( 1 less then the current one )
It would be less confusing if we considered nonce validity in terms of ticks, and not in terms of hours.
So the best way to describe the validity would be
- 0-12 hours == current tick value == t
- 12-24 hours == current tick value - 1 == previous tick value == t - 1
I hope I made things clearer