WordPress REST API, Expired Nonce from Cache results in 403 forbidden

My wordpress site sits behind Akamai, which is a cacheing service similar to Cloudflare.

I make the following API call:

GET /wp-json/mytheme/v1/get-posts?post_type=videos

This is done using apiFetch from ‘@wordpress/api-fetch’;

And it automatically includes this in the request header

X-WP-Nonce: 12323423

This works fine until 24 hours later, when the nonce expires.
The cache still continues to use the expired Nonce resulting in a 403 forbidden and a broken page.

If I make the same request without Nonce header, it works perfectly fine.

Is there a way in WordPress to disable or remove the Nonce for GET requests only?

Or even strip out the X-WP-Nonce header by intercepting the Request?

This my code for making the request which is being made from the wordpress frontend.

apiFetch({
     path: '/wp-json/mytheme/v1/get-posts?post_type=videos',
     parse: false,
});

2 Answers
2

Based on the authentication documentation here – a nonce key needs to be passed with each request.

So if the nonce key is being cached on the frontend beyond its lifespan, you will need to hook into the API request before the authentication step and replace the cached nonce key with a valid one.

WordPress provides a rest_send_nocache_headers filter for us to hook into (See here). This lets us perform an action before the authentication.

$send_no_cache_headers = apply_filters('rest_send_nocache_headers', is_user_logged_in());
if (!$send_no_cache_headers && !is_admin() && $_SERVER['REQUEST_METHOD'] == 'GET') {
    $nonce = wp_create_nonce('wp_rest');
    $_SERVER['HTTP_X_WP_NONCE'] = $nonce;
}

In the above example, we hook into the filter passing the is_user_logged_in() function as the parameter. This will return true or false.

Then in our query, if the user is not logged in, they are not in the admin and, this is a GET request we proceed with switching the invalid nonce key with a valid one.

Leave a Comment