Tutorials

Securing WordPress REST API: Complete Protection Guide

Protect your WordPress REST API endpoints with authentication, rate limiting, and access control measures.

S
Sarah Chen
8 min read
1,378 views
WordPress REST API security and protection guide

The WordPress REST API exposes site functionality to external applications. Without proper security, it can leak data and provide attack vectors.

REST API Security Concerns

Default Exposures

  • User enumeration via /wp-json/wp/v2/users
  • Content access without authentication
  • Site information disclosure
  • Plugin/theme information leaks

Authentication Methods

Cookie Authentication

// Built-in for logged-in users
// Requires nonce for write operations
wp_localize_script('my-script', 'wpApiSettings', array(
    'root' => esc_url_raw(rest_url()),
    'nonce' => wp_create_nonce('wp_rest')
));

// JavaScript fetch with nonce
fetch(wpApiSettings.root + 'wp/v2/posts', {
    headers: {
        'X-WP-Nonce': wpApiSettings.nonce
    }
});

Application Passwords

// WordPress 5.6+ built-in feature
// Create in User Profile
// Use with Basic Auth header

Authorization: Basic base64(username:application_password)

// PHP example
$auth = base64_encode('username:xxxx xxxx xxxx xxxx xxxx xxxx');
$response = wp_remote_get(rest_url('wp/v2/posts'), array(
    'headers' => array(
        'Authorization' => 'Basic ' . $auth
    )
));

Restrict User Endpoint

Hide User Information

// Remove users endpoint
add_filter('rest_endpoints', 'wpfs_remove_user_endpoint');
function wpfs_remove_user_endpoint($endpoints) {
    if (isset($endpoints['/wp/v2/users'])) {
        unset($endpoints['/wp/v2/users']);
    }
    if (isset($endpoints['/wp/v2/users/(?P[\d]+)'])) {
        unset($endpoints['/wp/v2/users/(?P[\d]+)']);
    }
    return $endpoints;
}

// Or require authentication for users endpoint
add_filter('rest_authentication_errors', 'wpfs_restrict_users_api');
function wpfs_restrict_users_api($result) {
    if (strpos($_SERVER['REQUEST_URI'], '/wp/v2/users') !== false) {
        if (!is_user_logged_in()) {
            return new WP_Error(
                'rest_forbidden',
                'Authentication required',
                array('status' => 401)
            );
        }
    }
    return $result;
}

Rate Limiting

Implement API Rate Limits

add_filter('rest_pre_dispatch', 'wpfs_api_rate_limit', 10, 3);
function wpfs_api_rate_limit($result, $server, $request) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $transient_key = 'api_rate_' . md5($ip);

    $requests = get_transient($transient_key) ?: 0;
    $limit = 100; // requests per minute

    if ($requests >= $limit) {
        return new WP_Error(
            'rate_limit_exceeded',
            'Too many requests',
            array('status' => 429)
        );
    }

    set_transient($transient_key, $requests + 1, 60);

    return $result;
}

Custom Endpoint Security

Secure Custom Endpoints

// Register secure endpoint
register_rest_route('wpfs/v1', '/secure-data', array(
    'methods' => 'GET',
    'callback' => 'wpfs_secure_data_callback',
    'permission_callback' => function() {
        return current_user_can('edit_posts');
    }
));

function wpfs_secure_data_callback($request) {
    // Additional validation
    $param = sanitize_text_field($request->get_param('id'));

    if (empty($param)) {
        return new WP_Error(
            'invalid_param',
            'ID required',
            array('status' => 400)
        );
    }

    // Return data
    return new WP_REST_Response(array('data' => $result), 200);
}

Input Validation

Validate and Sanitize

register_rest_route('wpfs/v1', '/submit', array(
    'methods' => 'POST',
    'callback' => 'wpfs_handle_submission',
    'permission_callback' => '__return_true',
    'args' => array(
        'email' => array(
            'required' => true,
            'validate_callback' => function($param) {
                return is_email($param);
            },
            'sanitize_callback' => 'sanitize_email'
        ),
        'message' => array(
            'required' => true,
            'sanitize_callback' => 'sanitize_textarea_field'
        )
    )
));

Disable REST API (If Not Needed)

Complete Disable

// Disable for non-logged-in users
add_filter('rest_authentication_errors', 'wpfs_disable_rest_api');
function wpfs_disable_rest_api($result) {
    if (!is_user_logged_in()) {
        return new WP_Error(
            'rest_disabled',
            'REST API disabled',
            array('status' => 403)
        );
    }
    return $result;
}

CORS Configuration

Restrict Origins

add_action('rest_api_init', 'wpfs_cors_headers');
function wpfs_cors_headers() {
    $allowed_origins = array(
        'https://yoursite.com',
        'https://app.yoursite.com'
    );

    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';

    if (in_array($origin, $allowed_origins)) {
        header('Access-Control-Allow-Origin: ' . $origin);
    }

    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Authorization, Content-Type');
}

Logging API Requests

add_action('rest_api_init', 'wpfs_log_api_requests');
function wpfs_log_api_requests() {
    $request_uri = $_SERVER['REQUEST_URI'];
    $method = $_SERVER['REQUEST_METHOD'];
    $ip = $_SERVER['REMOTE_ADDR'];

    error_log(sprintf(
        'REST API: %s %s from %s',
        $method,
        $request_uri,
        $ip
    ));
}

Conclusion

REST API security requires authentication, rate limiting, and careful endpoint exposure. Disable or restrict endpoints you don't need, validate all inputs, and monitor API usage.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

The Ultimate Guide to WordPress Security in 2026
The Ultimate Guide to WordPress Security in 2026

Learn how to protect your WordPress website from hackers, malware, and security threats with this...

January 15, 2026
How to Scan Your WordPress Site for SEO Spam and Hidden Malicious Content
How to Scan Your WordPress Site for SEO Spam and Hidden Malicious Content

Learn effective methods to scan your WordPress site for hidden SEO spam, malicious links, and...

January 13, 2026
How to Protect Your WordPress Uploads Folder from Malware
How to Protect Your WordPress Uploads Folder from Malware

The wp-content/uploads folder is one of the most vulnerable directories in WordPress. Learn how to...

January 13, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started