Как исправить 403 при запросах к WordPress REST API через Authorization header

Если REST API WordPress отвечает 403 Forbidden только для запросов с авторизацией, а обычные публичные эндпоинты работают, проблема чаще всего не в самом WordPress. На практике виноваты Nginx, прокси, модуль PHP-FPM, плагин безопасности или правило, которое режет заголовок Authorization до того, как запрос доходит до wp-json.

Ниже — рабочий сценарий диагностики и исправления для типичного сайта на WordPress, где API используют для мобильного приложения, внешнего сервиса, headless-фронтенда или интеграции с админкой.

Как выглядит проблема и что именно ломается

Симптомы обычно похожи друг на друга:

  • /wp-json/ открывается, но конкретный защищённый маршрут возвращает 403;
  • запрос с токеном или Basic Auth проходит локально, но падает на продакшене;
  • в логах WordPress нет нужной записи, потому что запрос блокируется раньше;
  • после включения плагина безопасности или CDN ошибка появляется только для API.

Важно разделять две ситуации: WordPress действительно отклоняет запрос по правам доступа и сервер режет заголовок или сам запрос на уровне веб-сервера. Это разные причины и разные исправления.

Диагностика: где именно возникает 403

Начинать лучше не с правки кода, а с проверки цепочки запроса. Это экономит время и помогает не лечить не ту проблему.

1. Проверить, доходит ли заголовок Authorization до PHP

Самый простой тест — временно вывести заголовки в лог или в небольшой mu-plugin. Если Authorization пустой, WordPress не сможет обработать токен или Basic Auth корректно.

<?php
/**
 * Plugin Name: Debug Authorization Header
 */
add_action('init', function () {
    if (defined('WP_DEBUG') && WP_DEBUG && isset($_SERVER['REQUEST_URI']) && str_contains($_SERVER['REQUEST_URI'], '/wp-json/')) {
        error_log('AUTH HEADER: ' . ($_SERVER['HTTP_AUTHORIZATION'] ?? 'EMPTY'));
    }
});

Если в лог попадает EMPTY, проблема почти наверняка на уровне Nginx, Apache, прокси или CDN.

2. Проверить ответ без плагинов безопасности

Если есть доступ к staging-копии, временно отключите плагины, которые фильтруют REST API, XML-RPC, заголовки или подозрительные запросы. Часто блокируют не весь API, а только методы POST, PUT или запросы с нестандартным User-Agent.

Для быстрой проверки удобно сделать запрос через curl:

curl -i https://example.com/wp-json/wp/v2/users/me \
  -H 'Authorization: Basic base64loginpassword'

Если на одном сервере запрос проходит, а на другом нет, сравнивайте не WordPress, а конфигурацию веб-сервера и промежуточных слоёв.

Почему Nginx часто режет Authorization header

В связке Nginx + PHP-FPM заголовок Authorization нередко не передаётся в PHP автоматически. Тогда WordPress видит запрос, но не видит данные авторизации. Для REST API это критично, если вы используете Basic Auth, Application Passwords или внешний шлюз, который полагается на этот заголовок.

Проверьте конфиг сайта в Nginx. В блоке location ~ \.php$ обычно нужен явный проброс:

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTP_AUTHORIZATION $http_authorization;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

На некоторых сборках вместо fastcgi_params используется fastcgi.conf. Смысл один: передать заголовок в PHP как переменную окружения.

Если перед вами Apache

Для Apache проблема встречается реже, но тоже бывает, особенно если сайт работает через CGI/FastCGI или за прокси. Тогда помогает правило в .htaccess или конфиге виртуального хоста:

RewriteEngine On
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Если запрос идёт через балансировщик или CDN, проверьте, не удаляет ли он заголовок на своём уровне. В таком случае правка WordPress не поможет.

Пошаговое решение: что менять и в каком порядке

Ниже порядок, который обычно даёт быстрый результат без лишних откатов.

Шаг 1. Исправить передачу заголовка на сервере

Сначала внесите правку в Nginx или Apache и перезапустите сервис. После этого повторите тест с curl. Если Authorization появился в логах PHP, половина проблемы уже решена.

Шаг 2. Проверить правила безопасности

Если заголовок доходит, но 403 остаётся, смотрите плагины безопасности, WAF и правила модерации запросов. Типичные причины:

  • блокировка REST API для неавторизованных пользователей;
  • запрет методов POST и DELETE для /wp-json/;
  • фильтрация по Authorization как по “подозрительному” заголовку;
  • защита от brute force, которая ошибочно срабатывает на API.

Если используется плагин, который умеет отключать лишние REST-эндпоинты, проверьте, не выключен ли нужный маршрут. Удобнее сначала протестировать на чистой staging-копии, а потом переносить изменения на боевой сайт.

Шаг 3. Убедиться, что WordPress не режет доступ сам

Если вы пишете свой endpoint через register_rest_route(), проверьте callback permission_callback. Ошибка часто не в авторизации, а в том, что callback всегда возвращает false или ожидает роль, которой у пользователя нет.

add_action('rest_api_init', function () {
    register_rest_route('myplugin/v1', '/profile', [
        'methods'  => 'GET',
        'callback' => 'myplugin_get_profile',
        'permission_callback' => function () {
            return current_user_can('read');
        },
    ]);
});

function myplugin_get_profile(WP_REST_Request $request) {
    return rest_ensure_response([
        'user_id' => get_current_user_id(),
        'email'   => wp_get_current_user()->user_email,
    ]);
}

Если permission_callback слишком жёсткий, WordPress вернёт rest_forbidden, и это уже не серверная проблема.

Как проверить, что решение сработало

Проверка должна быть не одной, а минимум в трёх точках:

  1. запрос через curl с нужным заголовком;
  2. тот же запрос из внешнего клиента или Postman;
  3. проверка в логах PHP-FPM, Nginx и WordPress debug log, если он включён.

Полезно сравнить ответы до и после правки:

ПодходЧто проверяетОграничение
curl с AuthorizationДоходит ли заголовок и отвечает ли маршрутНе показывает поведение браузера
Postman / InsomniaРеальный внешний клиентНужна ручная настройка
Логи Nginx/PHPГде именно теряется запросТребует доступа к серверу

Если после правки серверной конфигурации Authorization виден в PHP, а endpoint всё ещё отдаёт 403, значит проблема уже в правах пользователя, nonce, callback маршрута или плагине безопасности.

Частые ошибки и как их исправить

Забыли перезапустить PHP-FPM или Nginx

Конфиг изменили, но старый процесс продолжает работать. После правки проверьте, что сервисы действительно перечитали конфигурацию. Иначе вы будете искать несуществующую ошибку в коде.

Проверяют только главную страницу API

/wp-json/ может открываться, а конкретный маршрут — нет. Тестируйте именно тот endpoint, который использует приложение или интеграция.

Отключают все плагины на боевом сайте

Это рискованно и часто не нужно. Лучше сначала отключать только плагины, которые реально влияют на REST API, безопасность и кэш. На staging-копии это делается безопаснее и быстрее.

Путают 403 и 401

401 Unauthorized обычно означает, что аутентификация не прошла. 403 Forbidden чаще говорит о том, что доступ запрещён уже после проверки или запрос заблокирован политикой сервера/плагина.

Используют кэш там, где он не должен работать

Если CDN или page cache кэширует ответы REST API, можно получить странные 403 или устаревшие ответы. Для API обычно нужно исключать /wp-json/ из кэша, особенно если запросы зависят от авторизации.

Безопасность и производительность: что не стоит ломать ради быстрого фикса

Самая частая ошибка — “починить” API полным отключением защиты. Это плохая идея: вы уберёте симптом, но откроете поверхность атаки. Лучше точечно разрешить нужный маршрут, чем отключать фильтрацию целиком.

  • проверьте, что Authorization передаётся только там, где это нужно;
  • исключите REST API из HTML-кэша и агрессивного CDN-кэширования;
  • не отключайте весь плагин безопасности, если можно ослабить только одно правило;
  • если используете Application Passwords, убедитесь, что соединение идёт по HTTPS;
  • ведите лог ошибок на staging, а не на продакшене с открытым debug-выводом.

Если на сайте много дублей, мусорных архивов и лишних технических страниц, имеет смысл отдельно проверить SEO-настройки и чистку служебных URL. В таких случаях помогает не “магия”, а аккуратная настройка индексации и дублей, например через Clearfy Pro: https://wpshop.ru/plugins/clearfy.

Короткий чек-лист перед выкладкой на продакшен

  • заголовок Authorization доходит до PHP;
  • Nginx/Apache не режет запрос;
  • нужный REST-маршрут не заблокирован плагином безопасности;
  • permission_callback возвращает ожидаемое значение;
  • REST API исключён из кэша;
  • проверка пройдена через curl и внешний клиент;
  • в логах нет повторяющихся 403 на тот же endpoint.

Если после всех проверок ошибка остаётся, следующий шаг — сравнить рабочий и нерабочий сервер посимвольно: конфиг веб-сервера, PHP-FPM, список MU-плагинов, правила WAF и настройки CDN. В таких кейсах проблема почти всегда в одном конкретном слое, а не в WordPress как таковом.

Как исправить 403 при запросах к WordPress REST API через Authorization header
16.09.2026

Быстрый способ отслеживания ошибок WordPress: режим отладки.