I have a question about permission callbacks when working with the WP Rest API. I have registered a couple of endpoints using register_rest_route and simply want to secure them so that you can't access the content if you're not logged in.
add_action('rest_api_init', 'register_custom_endpoints');
function register_custom_endpoints(){
register_rest_route($base, $endpoint, [
'methods' => 'POST',
'callback' => function($request){
// Return JSON data
},
'permission_callback' => function($request){
// This always returns false
return is_user_logged_in();
},
]);
}
I think my logic here is correct but is_user_logged_in()
always returns false, meaning I'll never get the data even if I'm actually logged in. All I get is a 404 response:
{code: "rest_user_invalid_id", message: "Invalid user ID.", data: {status: 404}}
I've been scouring the web for answers and what I've found is that I need to send a nonce with the request. I've tried sending it both as body data and as a header. If I send it in the body, I can't verify it as it always returns false. And if I send it as a header, I get the same 404 response as stated above.
What am I missing here, and what am I doing wrong?
I recently encountered the same issue and it turns out that you need to create a nonce and pass it with your request headers.
You create the appropriate nonce with the following php code.
$nonce = wp_create_nonce( 'wp_rest' );
Then you pass that nonce with the HTTP request via the header X-WP-Nonce
.
Assuming your client is on the same domain (ergo has WordPress's auth cookies set) your session should be accessible via the REST API so functions like current_user_can
and is_user_logged_in
work as they would outside the REST API.
you can use current_user_can( 'edit_posts' );
it will only allow to admin user it work with me
for more info go to https://developer.wordpress.org/reference/functions/current_user_can/
A simple way to solve this is instead of permission_callback
parameter that check user logged in status
in the request handler function with a GET request URL parameter. You can add logged in user ID
or a temporary generated nonce / hash
in the URL and check on server side that they are the same or not, for example: domain.tld/wp-json/user/1/todo/
class UserAPI
{
public function __construct()
{
// do nothing
}
public function setHooks()
{
add_action('rest_api_init', [$this, 'actionRestApiInit']);
}
public function actionRestApiInit()
{
// add current user ID into GLOBALS to get it in the request handler function
$GLOBALS['user_id'] = get_current_user_id();
register_rest_route(
'user',
'(?P<userID>\d+)/(?P<action>[a-zA-Z0-9-]+)/',
[
'methods' => 'GET',
'callback' => [$this, 'runAction'],
]
);
}
public function runAction(\WP_REST_Request $data=null)
{
$params = $data->get_params();
if ((int)$params['userID']!==(int)$GLOBALS['user_id']) {
return new \WP_Error( 'rest_forbidden', __('Sorry, you are not allowed to do that.'), ['status' => 401] );
}
wp_send_json(['Logged in, run api'], 200);
}
}
(new UserAPI())->setHooks();
Or as a rest route attribute:
register_rest_route(
'user',
'(?P<userID>\d+)/(?P<action>[a-zA-Z0-9-]+)/',
[
'methods' => 'GET',
'callback' => [$this, 'userActions'],
'user_ID' => get_current_user_id(),
]
);
and than:
if ( (int) $params['userID'] !== (int) $data->get_attributes()['user_ID'] )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.