How to Secure Your WordPress REST API
The WordPress REST API enables powerful integrations but can expose sensitive data. Learn how to secure your REST API endpoints properly.
Understanding the WordPress REST API
The WordPress REST API provides a standardized way to access WordPress data using HTTP requests. Introduced in WordPress 4.7, it enables headless WordPress setups, mobile applications, and third-party integrations to interact with your site programmatically.
While powerful and useful, the REST API can expose information that helps attackers target your site. Understanding and securing these endpoints is essential for WordPress security.
Security Concerns with REST API
User Enumeration
By default, the /wp-json/wp/v2/users endpoint reveals usernames of anyone who has published content. Attackers use this information for targeted attacks.
Content Exposure
The API may expose draft posts, private content, or sensitive custom fields depending on your configuration.
Authentication Vulnerabilities
Improperly secured custom endpoints may allow unauthorized access to sensitive functionality.
Rate Limiting Absence
Without rate limiting, attackers can abuse API endpoints for brute force attacks or denial of service.
Securing REST API Endpoints
Disable User Enumeration
Prevent the users endpoint from revealing usernames to unauthenticated users:
add_filter('rest_endpoints', function($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P[\d]+)']);
}
return $endpoints;
});
Require Authentication
Force authentication for all REST API requests:
add_filter('rest_authentication_errors', function($result) {
if (!is_user_logged_in()) {
return new WP_Error(
'rest_not_logged_in',
'You must be logged in to access the API.',
array('status' => 401)
);
}
return $result;
});
Note: This may break public-facing features that use the API. Apply selectively.
Selective Endpoint Protection
Protect specific endpoints while leaving others public:
add_filter('rest_authentication_errors', function($result) {
$restricted_routes = array('/wp/v2/users', '/wp/v2/settings');
$current_route = $GLOBALS['wp']->query_vars['rest_route'] ?? '';
foreach ($restricted_routes as $route) {
if (strpos($current_route, $route) === 0 && !is_user_logged_in()) {
return new WP_Error('rest_forbidden', 'Authentication required.', array('status' => 403));
}
}
return $result;
});
Authentication Methods
Cookie Authentication
Built-in authentication for logged-in users. Requires a nonce for security:
wp_localize_script('my-script', 'wpApiSettings', array(
'root' => esc_url_raw(rest_url()),
'nonce' => wp_create_nonce('wp_rest')
));
Application Passwords
WordPress 5.6+ includes Application Passwords for API authentication:
- Generate in user profile
- Use with HTTP Basic Auth
- Can be revoked individually
JWT Authentication
JSON Web Tokens provide stateless authentication:
- Install a JWT plugin
- Request token with credentials
- Include token in Authorization header
OAuth 2.0
For complex applications requiring delegated access, implement OAuth 2.0 through plugins.
Implementing Rate Limiting
Protect against API abuse with request limiting:
add_action('rest_api_init', function() {
$ip = $_SERVER['REMOTE_ADDR'];
$transient_key = 'rest_rate_' . md5($ip);
$requests = get_transient($transient_key) ?: 0;
if ($requests > 100) { // 100 requests per minute
wp_die('Rate limit exceeded', 'Too Many Requests', array('response' => 429));
}
set_transient($transient_key, $requests + 1, 60);
});
Securing Custom Endpoints
Permission Callbacks
Always define permission_callback for custom endpoints:
register_rest_route('myplugin/v1', '/sensitive-data', array(
'methods' => 'GET',
'callback' => 'get_sensitive_data',
'permission_callback' => function() {
return current_user_can('manage_options');
}
));
Never Use __return_true
Using __return_true as permission_callback makes your endpoint public. Always implement proper permission checks.
Validate and Sanitize
Validate all input parameters:
'args' => array(
'id' => array(
'validate_callback' => function($param) {
return is_numeric($param);
},
'sanitize_callback' => 'absint'
)
)
Monitoring API Activity
Log API Requests
Track REST API usage to identify abuse:
- Request endpoints accessed
- IP addresses
- Authentication status
- Response codes
Alert on Anomalies
Configure alerts for:
- High request volumes from single IP
- Authentication failures
- Access to sensitive endpoints
- Unusual request patterns
Completely Disabling REST API
If you don't need the REST API at all:
add_filter('rest_authentication_errors', function($result) {
if (!is_user_logged_in()) {
return new WP_Error(
'rest_disabled',
'REST API is disabled.',
array('status' => 403)
);
}
return $result;
});
Warning: This breaks many plugins and features that rely on the REST API, including the Block Editor.
Conclusion
The WordPress REST API is powerful but requires careful security consideration. Disable unnecessary endpoints, implement proper authentication, add rate limiting, and monitor usage to maintain a secure API implementation.
Written by Sarah Chen
WP Folder Shield Team