What is a Nonce?

Vu Nam Hung
Vu Nam Hung
Published in
11 min readJul 6, 2017

A nonce simply stands for a Number used ONCE. It’s a unique token used to add a layer of security to your application and also to validate the intent of a user initiated action.

This Nonce is generated by a server-side application, stored on the server and sent to the client to be part of the payload it’s going to send back to the server. This way, you have a way to validate the payload and have a higher level of certainty that the request was actually made by the client.

Why use a Nonce?

A nonce could be seen as a one time password for user initiated actions. May it be sending a form, encrypting data or executing an action, the nonce adds a level of security by preventing a malicious script sending forged requests to your application. This is called Cross Site Request Forgery ( CSRF or XSRF ) and malicious scripts use this method to send requests on your server in a way that you have not intended to. This can have important consequences depending on what your script is used for.

An example of this is an attacker putting up a script on his website that POST to a form on your website automatically on an authenticated user session without the user really wanting to do that specific action. That was a mouthful! In other words, an attacker disguising a link to your authenticated user doing something (potentially bad) that the user never intended to do.

So if your form doesn’t contain a nonce, then there is not much that prevents an attacker to flood bad data in your database, potentially bringing down your whole site or worse, costing you or your users to lose money or to leak private information. If your form contains a nonce, then the POST would not go through since the nonce would not be able to be validate positively coming really coming from that user. It would not satisfy the intent part of the request.

This example includes forms as it’s an easy target for CSRF, but really, any requests made to a server that a script is listening for is vulnerable to CSRF if no precaution are taken to prevent it.

Breaking down the process of a nonce, it should look something like this:

  1. The server generates the unique token ( nonce ), stores it locally and passes it on to the client.
  2. The client does it’s thing, prepares the payload and includes the nonce in it.
  3. When the server receives the payload, it first checks if it contains a nonce, then, it will validate it by comparing it to the one stored locally. If a match can be made, the payload is considered genuine. If not, the payload should not be trusted.
  4. After the validation returned a match, the process should invalidate ( or destroy ) the nonce for it to be a true used ONCE number.

If you properly create your nonce, CSRF should not be a problem. Since a properly formed nonce should contain at least a secret key ( like a secret salt securely stored on your server ) and a unique or at least very descriptive action as a name ( maybe including a timestamp ? ), then there is no way an attacker could recreate a valid nonce without having access to both parameters.

So a true nonce would be destroyed after it’s been validated, effectively preventing an action of being performed twice ( or multiple times ), may it be maliciously or accidentally, without being validated again by a new nonce. A nonce also prevents CSRF attacks since secret salts and other unique parameters are used to created the nonce and are not available to an attacker to replicate a fake nonce.

About WordPress Nonces Implementation

Ok, so now that we explained what a nonce is, let’s see why WordPress nonces are not true nonces.

The way WordPress implements nonces lacks the one part that makes a nonce a nonce, it’s “used ONCE” part.

WordPress creates a nonce that will remain valid for at least 12 hours by default (can be valid for up to 24 hours). This implementation in itself invalidates the definition of a true nonce because a generated nonce can be used an unlimited amount of time, within that valid period. A new one will be generated every 12 hours (UTC time), and will remain valid for a maximum of another 12 hours depending on when it was generated within the tick cycle (See graph below).

Tick tock

This brings me to talk about ticks.

Ticks are what WordPress uses, as one parameter, to create a nonce.

It is generated by the wp_nonce_tick() function used in the nonce creation process.

So what is a tick? It’s a value that changes a midnight (+1 second) and midday (+1 second) by 1 unit. So every 12 hours (UTC time).

You might have read that a WordPress nonces are valid for 24 hours, but that’s just not true. At least not entirely.

A WordPress nonce is valid for a maximum of 24 hours. Or in truer terms, it is valid for the current tick’s value and the previous one.

But since a tick changes every 12 hours, a nonce will only truly be valid for 24 hours if it’s created at the beginning of the tick, specifically, at hour 0:00:01 or 12:00:01. The more you advance towards the end of the current tick, the shorter the lifespan of the nonce will be (or closer to a lifespan of 12 hours).

As you can see in the graph, a nonce created within the end of a tick, will have a shorter lifespan than a one created towards the beginning. This is because a wp nonce is generated with that tick’s value as one of it’s parameters. If we look at how wp_verify_nonce() verifies a nonce, we’ll see that it checks the current tick value, and the previous one (tick — 1). If the wp nonce is verified close to 24 hours later and it was created deeper within the cycle of the tick, then the nonce would be 2 ticks behind, failing the verification.

On the graph, only NONCE 1, 13 and 25 will be valid for close to 24 hours, assuming they are generated at the beginning of the hours not the end of it.

I agree that in reality, this should not be that much of an issue, since nonce should be used relatively quickly after their creation to verify actions/requests.

But it’s a misconception thinking that WordPress nonces are valid for 24 hours, when in reality, we should say they are valid for 2 ticks or for a maximum of 24 hours.

And it’s not a good idea to rely on WordPress nonces to validate an action that could take more than 12 hours for a user to actually request. Since the nonce will become invalid anywhere between 12 and 24 hours, chances are that the nonce validation would fail and results in unexpected behaviours

WordPress Nonces functions

Here’s a list of useful WordPress functions to manipulate nonces

Creation functions

Verification functions

Other functions

WordPress Nonces hooks

Also, here’s some hooks you might find useful

Invalidating WordPress Nonces

Like I discussed above, nonces will auto expire in maximum 24 hours after they’ve been created.

But I prefer to say, they will auto expire 2 ticks from now.

The other way a nonce can become invalid is if a user’s session token changes. That state change occurs when a user logs out and back in again. Since a new session token is generated, all previous nonces won’t validate anymore.

To make things clearer, WordPress doesn’t store the nonce it creates for a user. Instead, it stores the session token and will use it to rehash a nonce upon validation. If the session has not changed and the nonce is still within the 2 ticks valid period, then the submitted nonce and the rehashed one will match. Of course, like I just told you, if either the current tick is 2 or greater than the one used to create the nonce or the session token changes, then the nonce is invalid.

Security Concerns

WordPress not offering true nonces doesn’t mean you should not implement it within your application. It’s still useful to prevent CSRF.

But you should not rely on nonces to securely allow actions that should be restricted to specific users or users roles within your WordPress installation.

Your scripts should only allow such actions for users with the right capabilities (permissions) to do so.

Here, your best tool to use is current_user_can() and wrap your functions within this check.

Remember that nonces will tell you that the payload is from a genuine source (user), but it does not tell you if that source has sufficient permission to actually execute the payload.

This should be taken care of by another process, thus checking against capabilities.

Using WordPress Nonces

Ok, let’s give you a few example to show you how easy it is to implement a nonce in your code.

Like I listed above, there are 3 functions available to create a nonce wp_create_nonce(), wp_nonce_field() and wp_nonce_url().

wp_create_nonce()

The first one is a general usage function, meaning you can use the created nonce anywhere you would like.

The function takes 1 parameter, the $action name (optional) and returns the nonce for you to use.

While the action name is optional, it is recommended to supply one as specific to the action as possible. This will prevent a user having the same nonce for 2 different actions. For instance, deleting a custom post type and sending an email.

So let’s say I have a plugin that sends email to my users. The user I want to send an email to is stored in $send_to_id. I will then pass that user id value in the request so I can used again when I’ll be verifying the nonce.

Then to create a unique action nonce I would simply do it like this

$send_nonce = wp_create_nonce( ‘send_email_user_’ . $send_to_id );

This could then be used within an URL like this

<a href=”send_mail.php?action=send_user_email&nonce_token=<?php echo esc_attr( $send_nonce ); ?>&user=<?php echo esc_attr( $send_to_id ); ?>”><?php esc_html_e( ‘Send Email to User’, ‘textdomain’ ); ?></a>

wp_nonce_field()

This function will output or return the nonce and markup for an hidden form input.

This function takes 4 optional parameters. In order with their default values: $action = -1, $name = “_wpnonce”, $referer = true and $echo = true

Again, while optional, it is recommended to provide better security, to set a custom and specific $action value and a custom $name for the field. The value of $name will be the name of the field what you will use to retrieve the value of the created nonce in your request ( $_REQUEST, $_POST or $_GET ).

The $referer parameter outputs a second hidden field with the name _wp_http_referer containing the value of the referrer URL as found in the ‘REQUEST_URI’ element of the $_SERVER PHP superglobal variable, unless it is set to false.

Finally, the wp_nonce_fields() function prints by default the field, but if you set $echo to false the function will return it so you can use it within PHP.

So, reusing the same sending email example as above, creating the nonce and outputting the nonce and referrer fields using this function is as simple as

<form method=”post”>

<! — some form inputs here … →

<input type=hidden name=”user” value=”<?php echo esc_attr( $send_to_id ); ?>”>

<?php wp_nonce_field( ‘send_email_user_’ . $send_to_id, ‘nonce_token’ ); ?>

</form>

wp_nonce_url()

This third function provided by WordPress to create a nonce, outputs an escaped and formed URL containing your nonce.

This functions takes in 3 parameters. In order, with their default value: $actionurl, $action = -1 and $name = “_wpnonce”.

$actionurl is required and is the URL to which you should add your nonce. Here also, providing a descriptive and unique action name and custom name for the query string is optional, but recommended.

Using again the scenario above: sending an email to a user. Here’s what it would look like using wp_nonce_url()

<?php

$url = wp_nonce_url( admin_url(), ‘send_email_user_’ . $send_to_id, ‘nonce_token’ );

$url = add_query_arg( ‘user’, $send_to_id, $url ); // Add the id of the user we send to

?>

<a href=”<?php echo $url; ?>”><?php esc_html_e( ‘Send Email to User’, ‘textdomain’ ); ?></a>

wp_verify_nonce()

Once you have created your nonce, and used it, you need a way to verify it. Your general goto function to complete this will be wp_verify_nonce().

This function takes in 2 parameters, the first one, $nonce is required and is the actual value of the nonce. The second one, $action is optional, but you will need to provide it if you used an action name when creating your nonce. Remember that action names are recommended practice.

So let’s see how to use the function, still using our send email example.

$nonce = $_REQUEST[ ‘nonce_token’ ];

$send_to_id = $_REQUEST[ ‘user’ ];

if ( ! wp_verify_nonce( $nonce, ‘send_email_user_’ . $send_to_id ) ) {

die( __( ‘Security check’, ‘textdomain’ ) );

} else {

// Nonce validated. Do stuff here.

}

Since wp_verify_nonce() will return 1 if the nonce was generated within the current tick value and 2 if the nonce was generated in the previous tick value. Then you could do different stuff based on when the nonce was generated.

$nonce = $_REQUEST[ ‘nonce_token’ ];

$send_to_id = $_REQUEST[ ‘user’ ];

$nonce = wp_verify_nonce( $nonce, ‘send_email_user_’ . $send_to_id );

switch ( $nonce ) {

case 1:

echo ‘Nonce was generated in the current tick’;

break;

case 2:

echo ‘Nonce was generated in the previous tick’;

break;

default:

exit( ‘Nonce is invalid’ );

}

check_admin_referer()

Another function you can use to verify a nonce is check_admin_referer(). While the name is improper and may be misleading, it is still kept for backward compatibility. Also, know that using this function without providing an $action is obsolete since version 3.2.

So basically, this function now behaves the same as wp_verify_nonce() except it will die calling the wp_nonce_ays() function which display the Are you sure? message.

Example of usage

$nonce = $_REQUEST[ ‘nonce_token’ ];

$send_to_id = $_REQUEST[ ‘user’ ];

if ( check_admin_referer( $nonce, ‘send_email_user_’ . $send_to_id ) ) {

// Nonce validated. Do stuff here.

}

check_ajax_referer()

A last way to verify a nonce would be using the check_ajax_referer() function.

As the name of the function implies, this last validation function is best used within AJAX request to prevent processing request external to the blog.

The function takes 3 parameters. They are with they default values: $action = -1, $query_arg = false and $die = true.

The to verify the action, you call check_ajax_referer() hooking into the dynamic wp AJAX hook endpoint.

<?php

//Set Your Nonce

$ajax_nonce = wp_create_nonce( ‘send_email_user_’ . $send_to_id );

?>

<script type=”text/javascript”>

jQuery(document).ready(function($){

var data = {

action: ‘bn_ajax_send_email_user’,

nonce_token: ‘<?php echo $ajax_nonce; ?>’,

user: ‘<?php echo $send_to_id; ?>’

};

$.post(ajaxurl, data, function(response) {

alert(“Response: “ + response);

});

});

</script>

then you hook a custom function to the action defined in your javascript AJAX definition.

add_action( ‘wp_ajax_bn_ajax_send_email_user’, ‘bn_ajax_send_email_user_callback’ );

function bn_ajax_send_email_user_callback() {

if ( check_ajax_referer( ‘wpdocs-special-string’, ‘nonce_token’ ) ) {

bn_send_email( $_REQUEST[ ‘user’ ] );

wp_die(); // Need to exit the AJAX callback

}

}

WordPress True Nonce

While implementing your nonce methods could be relatively easy to implement, why reinvent the wheel when you could start of by using what’s done already!

There’s a repo on github called wp-simple-nonce that works just fine and will bring you true nonce for you to implement in your application.

While WordPress nonces implementation is good to prevent CSRF, it is not very useful to prevent multiple submission of the same data, which is often a reason to implement nonces within your application. This is why you might want to take a look at WP Simple Nonce

Wrap up

I hope you found this post constructive, if you have questions, comments or concerns, let me know by commenting below!

Cheers!

--

--