NONCE Upon a time in WordPress

Cal Evans, Developer Advocate Reading estimate: 11 minutes

NONCE upon a time we didn’t need to worry about Cross-Site Request Forgeries. We handled users submitting a form twice by simply processing the form twice. Neither of these were great strategies, so someone invented the Number used ONCE or "NONCE". Let’s take a quick look at what they are, how WordPress implements them, and how you can implement them in your own forms and code.

Introduction

WordPress is a massive beast of code. I know developers that have been working with it for years and still find new features to play with that they had no idea were there. This is often the case with WordPress’ internal NONCE implementation. Most of the systems I’ve built or worked on in the past 10 years have contained their own implementation of NONCE in one form or another, so when I first discovered that WordPress has an internal implementation, I was very happy. NONCE systems aren’t too hard to build, as we will see, but it’s nice not to have to invent the wheel every now and then.  Of course, as with everything in WordPress, there is good and there is bad.

Good:

WordPress has an internal NONCE system with several useful functions to generate and check them. For internal WordPress tasks, and many plugins, these functions will get the job done just fine.  

Bad:

WordPress’ internal NONCE implementation isn’t a true NONCE in that you can use it more than once. The concept of “Used Once” is at the heart of NONCE. While what WordPress has in it’s core is useful in many cases, it is not a NONCE.

Before you get started

If you want to play with the code in this article, you can create a test page and template on one of your blogs and put the code in the template to see it execute. However, it’s probably easier to setup a Pantheon account sandbox and create a WordPress instance that you can play with. This way you don’t risk a production site and when you are done with it, you can simply destroy the sandbox and move on. Visit https://dashboard.getpantheon.com/register   to create your account and then follow the instructions to get a WordPress install setup.

What is a NONCE

NONCE is a Number Used Once. The term has wider implications in that it can reference anything that is only used once. However in developer circles, NONCE usually refers to a token generated by a system that can only be used a single time. Many times, NONCEs are used in cryptographic schemes. A server-side piece of software will generate it, hand it to the client, the client will use it as part of the encryption or hashing algorithm, and then the server can reproduce the results when the encrypted or hashed payload comes back to it. There are however, much simpler uses for NONCEs.

Why do you need a NONCE?

One of the easiest to understand uses of a NONCE is to prevent Cross-Site Request Forgerie s . Depending on what you are reading, you may see the term NONCE and CSRF Token used interchangeably. The important thing to remember is that in both cases, the process looks like this.  

  1. The server generates a token, stores it locally, and then hands it to the client.
  2. The client does it’s thing and prepares a payload to return to the server, this is usuallya form, but it could be anything really. In the process of preparing the payload, it includes the NONCE.
  3. When the payload is returned, the server checks the payload for a NONCE. If one is found, and if it is the one that the server has stored locally, then the payload is considered to be genuine. If the NONCE is wrong, or if the NONCE does not exist at all, the payload is considered to be invalid.
  4. Regardless of whether the NONCE was valid or not, checking a NONCE should also invalidate it. This is the “Used Once” part of NONCE.

If some malicious person puts a script on their website that automatically POSTs to a form on your site everytime a user visits their site, you will be inundated with form submissions and your database could be polluted with bad data or spam. Worse yet, it could trigger some transaction on your site that costs you or your users' money, or falsifies actions.

However, if your form — the real one — includes a NONCE, and your script matches the NONCE as part of handling submission, the malicious user is out of luck. Your script will see that either they don’t have a NONCE, or that the NONCE is invalid, and will abort the script processing.

Another common use of a NONCE is similar in nature but has a different goal. Adding a NONCE to a form ensures that the form is only submitted by the user once. Once the form is submitted, and the nonce is invalidated, the form cannot be re-submitted. If the user presses the back button and then re-submits the form, your system will not accept the data because the NONCE will fail validation. That’s the “Used Once” part of NONCE.

WordPress’ NONCE Implementation

This article is not here to cast disparagement on WordPress or it’s NONCE implementation. While I think they are misnamed, the WordPress NONCE functions are very useful within WordPress and serve an important function.

Overview/How they work

WordPress’ implementation of NONCE differs from a traditional NONCE in one very important point, the “Used Once” point. WordPress’ NONCE have a lifetime instead of being used only once. This means that while they are useful for what WordPress uses them for, they are not very useful for the strict case of a NONCE.  Let’s take a look at how the WordPress NONCE system is setup.

The WordPress NONCE system has eight functions.

Of these, most developers need to know and understand four.

These four are the heart of the system and if you understand these, you can use the others without a problem.

Additionally, there are four hooks defined that you can use with NONCE.

The important one in that list is the first one, nonce_life. The rest are useful but not in all cases.

Now that you know the tools, let’s look at how you would use them.

Different options

At the heart of the WordPress NONCE system are two functions, wp_create_nonce()

and wp_verify_nonce(). The functions are self-evident but to state the obvious, the first one will create a NONCE for you and the second one will check to see if a NONCE passed in is valid or not.  

The simplest way to show how things work is in a blank WordPress page. Create a page and create a PHP template file that you can put code in and have it execute. Once you’ve got that done, put this code in your page template.

I created a page named Test in my sandbox, and then cloned page.php into page-test.php. 

This page simply demonstrates the four main functions.wp_verify_nonce() can be used to validate any NONCE produced by any of the methods. However, since we are not submitting a form or clicking a URL in this simple example, we can’t demonstrate that. The method is the same though, you callwp_verify_nonce() with the value of the NONCE and the “Action” you named it when you created it. WordPress will validate that the value is correct for that action and that the value has not expired.

Two ways to expire a NONCE

WordPress’ NONCE system is built around the concept of the value has a lifetime. Not only does the value have to match what is stored by WordPress but is has to be within the lifetime window of the NONCE. By default, WordPress’ NONCEs expire 24 hours after they have been created. This means that anytime you call wp_create_nonce(‘MyNONCE’) within a 24 period, you will get the same value. To demonstrate this, refresh the test page we built. You will notice that the value displayed for wp_create_nonce() does not change. It will change when this one expires.  

The other trigger that will expire a NONCE in the WordPress system is a state change in the user. If the user logs in or out, all nonces are automatically expired. Expiring NONCEs on state change like this is akin to regenerating Session IDs in PHP upon state change. It helps protect admin urls that are NONCE protected. Once the user logs out and is no longer an Admin, any NONCE protected URL is automatically invalidated.

It’s Pluggable!

One of the things I love about WordPress is that it is so configurable and modifiable without having to hack the core.  Two of the main methods in the WordPress NONCE implementation are indeed pluggable.

  • wp_verify_nonce()
  • wp_create_nonce()

You can dramatically change how WordPress’ NONCE implementation works by simply overriding these two methods in your functions.php. That’s not as easy as it sounds though. WordPress  uses it’s internal NONCE implementation a LOT. If you go mucking around with it just to suit your own desires, you could break something horribly. Worse yet, you could introduce a security vulnerability into your system.

The problem with WordPress’ NONCE system

As powerful as WordPress’ NONCE implementation is, it has a fatal flaw for many uses. Not to be pedantic WordPress’ NONCE implementation misses the important concept of “Used Once”  Since WordPress’ NONCEs have a “lifetime” they can be used over and over again. As long as you know that going it, it’s not a terribly bad thing. However, it does preclude some of the more common uses of a NONCE, like the ones we discussed in the beginning.

In a recent project I was building, I needed a true NONCE in my WordPress system.  The existing WordPress system would not suffice because I needed to protect a form from being re-submitted. I didn’t want users to accidentally hit the back-button and be able to correct something and re-submit the form. Mainly though, this form collected email addresses in exchange for goodies. I didn’t want someone to put a form on their system that just made up bogus data to get their users access to my goodies. Thus I create SimpleNonce. (aka HeisenNONCE)

SimpleNonce - aka Heisen-Nonce

SimpleNonce is just that, a very simple nonce implementation. It is nowhere nearly as complex as WordPress’ NONCE implementation. It has 3 simple functions.

  1. It will create a NONCE
  2. It will create a hidden field with a NONCE, similar - but not identical - towp_nonce_field()
  3. It will validate a NONCE

The third one is very important in that it is very different from wp_verify_nonce(). When SimpleNonce checks a NONCE for validity, it also destroys it. You can only check it once, thus the HeisenNONCE name. This truly makes it “Used Once” as the act of validating the NONCE destroys it.

In this implementation NONCEs created with SimpleNonce also have a lifetime of 24 hours. That has nothing to do with SimpleNonce though, it comes from the storage mechanism we use to persist the NONCEs.

How it works

SimpleNonce is a single class with 3 static methods. To create a new NONCE, you make this call:

$myNonce = WPSimpleNonce::createNonce('myNonce');

The parameter you pass is in the root of the name of your NONCE. It should identify the purpose.

e.g.

  • freeVideoForm
  • contactUsForm
  • moreInfo
  • etc.

IMPORTANT: Because of the field length limitation in wp_options, and because we have to make this id unique, your name is limited to 17 characters. If you send in more, it will be truncated.

Calling createNonce() stores a copy of the NONCE on the server.  createNonce() will return to you an array with 2 elements.

  • Name 
    This is the new name of your NONCE. It will contain an md5 value at the end of the name you gave. This is so that this NONCE will be unique among all others. Make sure that when you pass your NONCE back into your system, you use this name and not just the root name you originally passed in.
  • Value 
    This is the value you will store and send back associated with the name in the element described above.

Validation

Once the NONCE comes back to you, you can validate it just as easily.

$result = WPSimpleNonce::checkNonce($nonceName,$nonceValue);

IMPORTANT: Make sure you pass in the name that was returned to you and not the name you gave your NONCE.

$result is now a boolean, true if the NONCE existed and was the exact same value as the value we passed in. Otherwise it is false. As we discussed before, executing checkNonce()will also invalidate the NONCE. Therefore it is a good idea to capture the results ofcheckNonce() in a variable so you can refer to it more than once. Any subsequent calls tocheckNonce() with the same name will always return false.

Implementing it

As you can see from the code below, I’ve updated our test page to show both NONCE implementations.

If you paste this code into your page-test.php template, and hen view the page, you can see both implementations. One thing you will notice is that as discussed above, the NONCE from the WordPress implementation will not change as you refresh the page, while the SimpleNonce one will change each time you refresh the page. Also, if you look at the code, you will notice that the code for displaying the invalid NONCE is exactly the same as the code used to display the valid one. This shows the “Used Once” principal.

ShortCode

Developers tend to be lazy people. Because of this, I’ve included code in wp-simple-nonce.php to register a short code with WordPress. This short code  will create a NONCE form field.  

The shortcode defined is [simpleNonceField]

You can pass in a name attribute if you like 
[simpleNonceField name=”myNonceField”]

Conclusion

A NONCE is a powerful tool for security, cryptography, or just preventing your users from making a nuisance of themselves. In many cases, WordPress’ NONCE implementation is powerful and flexible enough to get the job done for you. However, sometimes you need something more. Sometimes you will need a true NONCE. In those cases, SimpleNonce will get the job done for you.

Share

Discover More

Safely Publish to Web from Google Docs with Pantheon Content Publisher

Roland Benedetti (Senior Director, Product) and Zack Rosen (Co-Founder)
Reading estimate: 7 minutes

Unifying Content and Code: Inside Pantheon’s Vision for Content Operations

Chris Yates
Reading estimate: 5 minutes

How Pantheon Protects Your Site from Software Supply Chain Risks in Open Source

Steve Persch
Reading estimate: 8 minutes

Try Pantheon for Free

Join thousands of developers, marketers, and agencies creating magical digital experiences with Pantheon.