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.
If it helps, this is the REST point registration. As mentioned it works fine without the involvement of a nonce.
register_rest_route(
'my-namespace', //namespace
'my-namespace-route-1', //route
['methods'=>'POST',
'callback'=>['Another_Class',//class
'a_static_function'] //static function
] //params
);
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.
If it helps, this is the REST point registration. As mentioned it works fine without the involvement of a nonce.
register_rest_route(
'my-namespace', //namespace
'my-namespace-route-1', //route
['methods'=>'POST',
'callback'=>['Another_Class',//class
'a_static_function'] //static function
] //params
);
Share
Improve this question
edited Sep 19, 2020 at 0:51
dewd
asked Sep 18, 2020 at 22:41
dewddewd
17911 bronze badges
2
|
1 Answer
Reset to default 1This 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/reference/functions/wp_localize_script/.
admin-ajax.php
api rather than the a newer REST API endpoint viaregister_rest_route
? – Tom J Nowell ♦ Commented Sep 19, 2020 at 0:32