Fix WP Nonce Validation Failing On First Page Load

Broken Nonces

wp_verify_nonce failed

 

If you are having a strange nonce validation problem that ONLY happens when you first load a page, and you have Woocommerce running on this particular site, read on.


So you’re trying to make sure requests are all legit, and for some reason your nonces are failing. What gives? It’s not like this is rocket science, right? Well perhaps I can save you an hour or two of getting intimately acquainted with wp_create_nonce and wp_verify_nonce.

To quickly recap your situation, this is probably a Woocommerce page of items and there is something else you want to Ajaxify on the page. You click and send what should be a normal GET or POST request except the backend kicks back an Invalid Nonce error.

The Nonce Problem: What’s in a Nonce Anyway?

Each wordpress nonce has a couple of bits of information that it uses to create its hashed self. It has your $action of course, which could be anything (or nothing). It’s also going to be roughly tied to the time it was created, so that we can make sure it’s fresh and good. There will also be some session information used to create it, so that we can create unique nonces for each user.

Here’s the kicker though that is causing you grief: the User ID. In theory the User ID (let’s refer to it as $uid since that’s what the codebase calls it) should be empty for non logged in users. But Woocommerce needs something there, right? Something to save that cart to.

So Woocommerce is giving the user a $uid after your page has loaded, and when you compare the nonces they won’t match.

Why This Nonce Failure is Elusive

I actually wouldn’t blame you if this bug went almost unnoticed during development. Why? Well it only happens on unauthenticated page loads, and only on the first one. So if you are like me and logged into an admin account, or refreshing pages constantly as you work, you’ll miss it.

There’s also a subtlety to it… Or maybe I’m just super tired today, but after putting in some debug statements and looking at the F12 developer tools for returned JSON, it took a while to spot.

Solving the Nonce Validation $uid Problem

Basically what you need to do is add a filter that will target logged out users, and set the $uid value back to 0 when your custom action is called. So, you better be using custom actions.

Here is my oop solution that was for functionality on a custom post type:

class My_Custom_Post_Type{
    public __construct(){
        add_filter('nonce_user_logged_out', array($this, 'nonce_fix'), 100, 2);
    }

    public function nonce_fix($uid = 0, $action = ''){
        if($action == 'my-custom-action') return 0;

        return $uid;
    }
}

And you can also see this nonce validation issue solved similarly here: Woocommerce messes with nonces.

She builds websites and is for hire: custom WordPress websites & plugins. Scottsdale website development and design at reasonable prices by a savvy lady.

Last updated on