Identical wp_rest nonce returned from rest_api
TLDR: How can I force a new nonce to be returned, so that AJAX works without refreshing the page?
Following on from Nonces and Ajax request to REST API and verification I implemented the Nonce functionality, with callback permissions and the ‘intent’ of my routes are now secure.
I enqueue Axios, with wp_rest nonce as a local script setting.
// Register custom variables for the AJAX script.
wp_localize_script( 'axios', 'axiosScriptVars', [
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' ),
]);
I set my Ajax headers up with axiosScriptVars.nonce. I POST – this works. I return a NONCE from my REST_API endpoint’s response, and update my Ajax header ready for the next POST…
Example of my log in and log out route:
function ajax_logout() {
try {
wp_logout();
$nonce = wp_create_nonce( 'wp_rest' );
return array('loggedin'=>false, 'message'=>__('Logged out successfully'), 'name'=>false, 'email'=>false, 'nonce'=>$nonce );
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "n";
die;
}
}
function ajax_login(){
$_POST = json_decode(file_get_contents("php://input"),true);
$info = array();
$info['user_login'] = !empty($_POST['username']) ? sanitize_text_field( $_POST['username'] ) : null;
$info['user_password'] = !empty( $_POST['password'] ) ? sanitize_text_field( $_POST['password'] ) : null;
$info['remember'] = true;
$user = wp_signon( $info, true );
$nonce = wp_create_nonce( 'wp_rest' );
if ( is_wp_error($user) ){
return array('loggedin'=>false, 'message'=>__('Wrong username or password.'), 'name'=>false, 'email'=>false, 'nonce'=>$nonce );
} else {
return array('loggedin'=>true, 'message'=>__('Login successful'), 'name'=>$user->data->display_name, 'email'=>$user->data->user_email, 'nonce'=>$nonce );
}
}
add_action( 'rest_api_init', function () {
register_rest_route( 'rw-user/v1', '/log-in', array(
'methods' => 'POST',
'callback' => 'ajax_login',
'permission_callback' => '__return_true'
));
register_rest_route('rw-user/v1','/log-out', array(
'methods' => 'POST',
"callback" => 'ajax_logout',
"permission_callback" => function () {
return current_user_can( 'administrator' );
}
));
});
POSTING fails because the New NONCE is identical to the old.
So I thought WordPress must return a new nonce in the response header… I check and see the "x-wp-nonce" header – only it is also identical!
(I read something about not using wp_json_success in REST routes – as the rest api already turns the return of your function into a json response and sets the correct headers etc.)
When I hard refresh the page, I get a new nonce and my AJAX now works…
How can I force a new nonce to be returned, so that AJAX works without refreshing the page?
This post is kinda similar – Serving nonces through AJAX is not refreshing nonce, returning 403 error, but I can’t see anything in my code which is changing the user and invalidating the nonce…
Unless, the log in route – now logged in – changes the nonce, which doesn’t get returned?
Leave an answer
You must login or register to add a new answer .