The flawed login logic is breaking REST API nonces
-
I’ve been building a new plugin with a React-based admin UI, supporting both the Block Editor and Classic Editor. My design relies heavily on the REST API rather than the legacy
wp-ajaxsystem.Lately, I’ve run into a recurring issue: even though the UI shows I’m clearly logged in, the REST API keeps throwing 403 Forbidden errors.
Here’s the context of my environment:
- Browser storage cache is forced off.
- Absolutely no server-side or object caching is active.
- I am confirmed logged in; I can navigate the WP Admin dashboard freely without issues.
In the past, a manual logout and login would “fix” it, but I had a gut feeling this was a fundamental nonce exchange flaw. If I’m hitting this as a developer, there’s a high chance my users will too. So today, I decided to dig into the root cause.
To rule out my own code, I checked the WordPress Site Health page, even the core Site Health API calls were failing with a 403.

Upon inspecting the session cookies, I found two identical cookies with the same name but different paths. I traced the logic back to
pluggable.phphere:https://github.com/WordPress/WordPress/blob/59e1…/wp-includes/pluggable.php#L1193-L1195The most important
wordpress_logged_incookie is was completely missing, yet I could still browse the admin pages.
My dev environment is clean, just WordPress and WooCommerce for testing product features. No other plugins.
Steps to Reproduce:
Step 1:Log in normally. You’ll typically see three cookies:
- wordpress_{hash} (Path: /wp-admin)
- wordpress_{hash} (Path: /wp-content/plugins)
- wordpress_logged_in_{hash} (Path: /)
Step 2:
Manually delete the wordpress_logged_in cookie.
The Admin UI still works perfectly fine. You can click around and visit different pages. This feels like a security-level bug: the dashboard remains accessible even without the primary login cookie. However, the REST API is now officially broken (403), and Site Health is dead. This is because REST nonces rely on that specific logged_in cookie to validate.Step 3:
Delete the wordpress_{hash} cookie (Path: /wp-admin).
Only then are you finally kicked out to the login screen.
I haven’t fully investigated why thewordpress_logged_incookie disappears in the first place, but I don’t think that’s even the main point. The real issue is that modern WordPress admins rely heavily on the REST API, but the nonce generation is tied to thewordpress_logged_incookie, while the Admin UI itself is guarded by a completely different set of “admin-only” cookies.This is a fundamental design flaw. You have a situation where the system thinks you are “logged in enough” to see the dashboard, but “not logged in enough” to use the APIs that power that very dashboard.
You must be logged in to reply to this topic.