How to Secure REST API Endpoints in WordPress
1. Use Authentication
- Cookie Authentication → Default for logged-in users in wp-admin.
- Application Passwords (since WP 5.6) → Allows basic authentication without exposing main password.
- OAuth / JWT Authentication → For headless setups or external apps.
Example (JWT check in endpoint):
register_rest_route( 'myplugin/v1', '/data', array(
'methods' => 'GET',
'callback' => 'my_api_callback',
'permission_callback' => function() {
return current_user_can( 'edit_posts' ); // Only editors+ allowed
}
) );2. Use permission_callback
- Always validate user roles/capabilities before returning data.
- Avoid
__return_true(no security).
Example:
'permission_callback' => function() {
return current_user_can( 'manage_options' ); // Admin only
}3. Nonce Verification (for logged-in AJAX/REST)
- Generate nonce:
wp_create_nonce( 'wp_rest' );- Send it in the request header:
X-WP-Nonce: {nonce}- Verify in REST callback:
check_ajax_referer( 'wp_rest' );4. Limit Public Data Exposure
- Disable unnecessary default endpoints (like
/wp/v2/users) for non-authenticated users:
add_filter( 'rest_endpoints', function( $endpoints ) {
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'] );
}
return $endpoints;
});5. Data Validation & Sanitization
- Use
sanitize_text_field(),esc_url_raw(), etc. before saving. - Prevents malicious input or SQL injection.
✅ Best Practice Summary
- Require authentication for sensitive endpoints.
- Use
permission_callbackfor role checks. - Validate & sanitize all inputs.
- Disable unneeded default endpoints.
- Use HTTPS to prevent token sniffing.
