The WordPress REST API is publicly accessible for read operations on published content. For write operations — or reading private data — you need to authenticate. WordPress 4.x supports cookie authentication (for the admin dashboard) and can be extended with application passwords via a plugin. Here’s how both approaches work.
Problem: How do you authenticate requests to the WordPress REST API from an external application or a server-to-server script?
Solution: Use Application Passwords (built in since WordPress 5.6) — generate a per-application password in the user profile and send it as HTTP Basic Auth credentials with every API request.
Cookie authentication works automatically when JavaScript makes requests from within the WordPress admin. All you need is a valid nonce:
// WordPress localizes wpApiSettings on admin pages
fetch( wpApiSettings.root + 'wp/v2/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce,
},
body: JSON.stringify( {
title: 'My New Post',
content: 'Hello world.',
status: 'draft',
} ),
} )
.then( res => res.json() )
.then( post => console.log( 'Created post ID:', post.id ) );
Basic authentication (for development/testing only — requires HTTPS in production) using the Basic Auth plugin:
curl -X POST https://example.com/wp-json/wp/v2/posts -u "username:password" -H "Content-Type: application/json" -d '{"title":"Test","status":"draft"}'
To expose the nonce to your custom JavaScript on the front end:
add_action( 'wp_enqueue_scripts', function() {
wp_localize_script( 'my-script', 'wpApi', [
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' ),
] );
} );
NOTE: Never use Basic Authentication in production without HTTPS — credentials are sent as Base64, which is trivially decoded. For production front-end auth, use OAuth or Application Passwords (available via plugin for WordPress 4.x, built into core from WordPress 5.6).