1

I'm having trouble validating a nonce created with wp_create_nonce() inside a hidden input with the name nonce in an html form:

<input type="hidden" name="nonce" value="<?php echo wp_create_nonce('action_name'); ?>" />

The form submission is done via ajax and validated with check_ajax_referer('action_name','nonce'). This always returns -1. All REST endpoints have been tested without nonces and work 100% fine.

The issue seems to stem from wp's user identifcation.

My debugging so far

Nonce creation
Within wp-includes/pluggable.php wp_create_nonce('action_name') creates a nonce hashing various variables including the user id and the action.

Ajax call
I submit an ajax call which calls check_ajax_referer('action_name','nonce'). This in turn calls wp_verify_nonce($nonce,$action) which verifies the nonce by hashing the same variables and comparing the two.

Reverse engineering to locate problem
My problem is that wp_create_nonce('action_name') is being created with the correct user id. However, when I run check_ajax_referer('action_name','nonce') which calls wp_verify_nonce($nonce,$action) which in turn calls wp_get_current_user(); no user is found (user id is 0).

Evidence the problem is to do with user id

If I temporarily edit wp-includes/pluggable.php to force my user id, the nonce validation works fine. It's as if ajax requests to a known and valid endpoint are being treated as if the user is logged out regardless of whether they are or not.

I'm clearly missing something here, but I have no idea what.

dewd
  • 4,380
  • 3
  • 29
  • 43
  • I’m voting to close this question because This question belongs on another site in the Stack Exchange network ie wordpress. Unfortunately, the "This question belongs on another site in the Stack Exchange network" doesn't give the wordpress community as an option. – dewd Sep 18 '20 at 22:34
  • 1
    Same issue here. – Ty Kroll Sep 25 '20 at 08:59
  • @TyKroll see answer below. I created this question in https://wordpress.stackexchange.com (/questions/375099/wordpress-is-creating-nonce-as-a-logged-in-user-but-verifying-it-incorrectly/375172#375172 ) and tried to close this one. – dewd Sep 25 '20 at 13:47
  • any luck finding the solution ? I have the same issue. – Aravind Emmadishetty Apr 14 '22 at 08:17
  • 1
    @AravindEmmadishetty I added the answer below – dewd Apr 15 '22 at 16:31

1 Answers1

0

This is happening because a separate nonce with the action wp_rest is not being sent by the server to the client and received back from the client in an HTTP request header called X-WP-Nonce with every REST request.

To get this working, you will have to generate a nonce like this:

wp_create_nonce('wp_rest')

...and provide it to the client making the rest call. Once your client has the nonce value, you need to add it to every REST request e.g.:

headers: {
    'X-WP-Nonce': nonce,
}

Creating the nonce on the server and accessing it on the client can be done several ways. Using wp_localize_script() is the most common and probably best practice for WordPress. wp_localize_script() addds a global variable to the client for a script to access. See https://developer.wordpress.org/reference/functions/wp_localize_script/.

dewd
  • 4,380
  • 3
  • 29
  • 43