How do I disable nonce checking in a plugin?
-
Hi,
What changes do I need to make to the plugin’s code so that it stops checking the nonce? I don’t need it, and I’m not worried about security issues: see https://github.com/cabrerahector/wordpress-popular-posts/wiki/5.-FAQ#is-wordpress-popular-posts-compatible-with-caching-plugins
I don’t want to use global code like this:
add_filter( ‘nonce_life’, function () { return 604800; } );I just need to make sure WP Popular Posts stops relying on the nonce.
Thanks!
-
I tried targeting WP Popular Posts endpoints to extend the nonce lifetime, but it didn’t work.
add_action('rest_api_init', function() {
add_filter('rest_authentication_errors', function($errors) {
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
$path = wp_parse_url($request_uri, PHP_URL_PATH);
if ( strpos($path, 'wordpress-popular-posts/v2/') === false ) {
return $errors; //
}
add_filter('nonce_life', function($lifespan, $action) {
if ($action === 'wp_rest') {
return 365 * DAY_IN_SECONDS;
}
return $lifespan;
}, 10, 2);
return $errors;
}, 10);
});Hi there,
It’s within your right to make your site less secure if you wish to do so, however that’s not a sentiment I share. I don’t believe that reducing the security is worth whatever you’re trying to do. But that’s just me.
I have to ask, what exactly are you expecting to achieve with this?
Additionally, I’m not sure it’s possible to change the nonce lifetime for a specific request. I believe the nonce_lifetime filter hooks affects all nonces, not just the ones generated for WPP’s requests.
The crux of the problem is this: many posts on the site are evergreen, meaning there’s no point in regenerating the cache for them on a regular basis. In other words, the cache’s lifetime is infinite. This leads to the WPP nonce expiring. If you don’t use AJAX loading to display WPP, popular posts get cached as static content, meaning AJAX is necessary in any case.
My previous code really didn’t work for many reasons.
The solution is as follows. Remove the X-WP-Nonce header from the $_SERVER superglobal array for all REST requests to the wordpress-popular-posts/ namespace. WordPress will then not find the nonce and will not check it. Since the plugin’s endpoints are public (permission_callback => ‘__return_true’), they will work without a 403 error.
Why is this safe? WPP endpoints have permission_callback => ‘__return_true’, and they are public. The nonce is only needed for CSRF protection, which is not critical for public counters and widgets. No other REST endpoints are affected.
Here is the code:
add_action('rest_api_init', function() {
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
if (strpos($request_uri, '/wordpress-popular-posts/') !== false) {
unset($_SERVER['HTTP_X_WP_NONCE']);
}
}, 1);I’ll flag this topic as resolved since OP found a way to disable the nonce check (which they can do on their own site, it’s their prerogative) but to anyone else reading this in the future I highly recommend against using this solution on your site as it’s not safe to use.
@hcabrera Wait a minute, do you have any other solution that you think would be safe?
Let me repeat: the reliance on a nonce forces the site to periodically regenerate the cache, even though this is often a very resource-intensive process. Imagine you have tens of thousands of posts that are never updated, but for the WPP to work correctly, it has to perform background preloading of them after a certain amount of time has passed.
The safe approach would be to not remove the nonce check. There’s never a good reason to disable a security feature. It’d be preferable to at least extend the nonce lifetime than to disable it completely.
Cache regeneration can be resource intensive vs a static site, yes, but unless there’s some actual hard data showing that the site’s performance tanks in a noticeable way during cache regeneration for extended periods of time disabling / lowering security wouldn’t be the first measure I would take.
What I would do instead (in no particular order and not limited to):
- Set the page cache to expire every 12 hours or so to guarantee that there’s always a valid nonce available, or -as already mentioned before- at least increase the nonce expiry time (eg. 48 hours instead of the default 24) which does lower security but doesn’t remove it completely.
- If not already in place, enable object caching on the site so frequently accessed data is stored in memory which should help performance even while the page cache is being regenerated.
- Check for slow queries and/or other resource-intensive scripts.
One more thing: when it comes to caching plugins that offer “background preloading,” I generally prefer to keep that particular feature off.
The background preloading functionality -as I understand it at least- artificially generates static HTML files for a site’s pages before a visitor actually requests them. In paper that’s great because it reduces TTFB (Time to First Byte) but when you have a ton of pages (“tens of thousands” as you said) the background performance can be heavy due to CPU & RAM spikes (especially on shared / lower-end hosting environments.) At least that’s what logic tells me, I don’t have any actual data at hand to back this up so take this with a grain of salt.
You must be logged in to reply to this topic.