Despite you already figured it out or found a solution, since this is a follow-up to the other question, I thought it’d be benefecial to post this answer, so hopefully it helps you. =)
WordPress uses the native setcookie()
function in PHP for setting the authentication cookies, and $_COOKIE
for reading the cookies values. But the thing is, PHP doesn’t immediately update the values in the $_COOKIE
array and instead, it’ll only be updated once the page is reloaded.
So because WordPress nonces rely upon the current user and the authentication cookies, you’ll need to do these in order to get the correct nonce on the very same page/request — i.e. without page reloads:
-
Immediately update the
$_COOKIE
array once you’ve calledwp_signon()
(which callswp_set_auth_cookie()
). And you can do that using theset_logged_in_cookie
hook. -
And then call
wp_set_current_user()
after logging in the user — if you don’t call it, the generated nonce will not use the current user and functions likeis_user_logged_in()
andcurrent_user_can()
would also returnfalse
.
Working Example
function wpse_377570( $logged_in_cookie ) {
$_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie;
}
add_action( 'set_logged_in_cookie', 'wpse_377570' );
function ajax_login( $request ) {
// Logs the user in and set the authentication cookies.
$user = wp_signon( array(
'user_login' => $request->get_param( 'username' ),
'user_password' => $request->get_param( 'password' ),
'remember' => true,
) );
// In case of errors like wrong password, return the error object/data.
if ( is_wp_error( $user ) ) {
return $user;
}
// Now set the current user so that we get the correct nonce based on
// that user.
wp_set_current_user( $user->ID );
return [
'nonce' => wp_create_nonce( 'wp_rest' ),
'loggedin' => is_user_logged_in(),
// ... your other data.
];
}
Additional Notes
- REST API endpoint’s callback always receives the request object (a
WP_REST_Request
instance) as the first parameter, which among other functions, hasget_param()
for retrieving a parameter like a URL query string, a POST body data or a JSON payload, so you should make use of that and the other functions, just as I did in my example. 🙂