WordPress REST API 401 Unauthorized errors during Application Password synchronization occur when HTTP Basic Authentication headers are stripped by the web server (Apache/Nginx) before reaching PHP, or when security plugins block REST API authorization headers. When synchronizing external systems via Application Passwords, the Authorization: Basic <credentials> header must be parsed by wp_authenticate_application_password(). If the header fails to pass through reverse proxies, web application firewalls (WAF), or PHP-FPM execution layers, WordPress evaluates the request as an unauthenticated guest and rejects the API call.
Root Cause Diagnosis
When an application password request hits the REST API endpoint (/wp-json/wp/v2/), WordPress extracts the credentials from the HTTP Authorization request header. FastCGI, Apache (mod_cgi/mod_proxy_fcgi), and Nginx setups frequently scrub or fail to forward non-standard Authorization headers to the $_SERVER['HTTP_AUTHORIZATION'] environment variable by default. Consequently, the REST API cannot validate the Base64-encoded username and application password payload, resulting in a rest_cannot_access or rest_forbidden 401 HTTP response code.
Quick Fix
Pass the missing authorization header directly to PHP by adding the rewrite directive to your .htaccess file or re-exposing it in wp-config.php:
# Add to top of .htaccess
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
Or inject this fallback directly into wp-config.php:
// Force HTTP Authorization header parsing into PHP SERVER global
if (!isset($_SERVER['HTTP_AUTHORIZATION']) && isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
}
Step-by-Step Resolution
1. Configure Web Server to Pass Authorization Headers
For Apache Environments
Edit the .htaccess file located at your WordPress root directory (/var/www/html/.htaccess):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Pass the Authorization header to PHP
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
If running Apache with PHP via mod_proxy_fcgi, edit your virtual host configuration (/etc/apache2/sites-available/wordpress.conf):
<Directory /var/www/html>
CGIPassAuth On
</Directory>
Restart Apache:
sudo systemctl restart apache2
For Nginx Environments
Ensure the fastcgi_pass block in your server configuration (/etc/nginx/sites-available/wordpress.conf) explicitly forwards the Authorization header to PHP-FPM:
server {
# ... standard configuration ...
location ~ \.php$ {
include fastcgi_params;
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Reload Nginx:
sudo systemctl reload nginx
2. Verify Application Passwords Feature Status
Ensure that Application Passwords are not disabled by environment flags, plugins, or non-SSL connections.
Add this code to wp-config.php to ensure application passwords remain enabled over HTTPS:
// Ensure Application Passwords are enabled on SSL/HTTPS
add_filter('wp_is_application_passwords_available', '__return_true');
3. Exclude REST API Routes from WAF and Security Plugins
Security plugins (such as Wordfence, iThemes Security, or Cloudflare WAF) often mark Basic Auth requests to /wp-json/ as brute-force attacks.
- Cloudflare: Create a Web Application Firewall Rule to bypass
BlockorManaged Challengeactions for requests where URI path starts with/wp-json/and theAuthorizationheader is present. - ModSecurity: Add a rule exclusion for Rule ID
920350(Host header is a numeric IP address or missing Basic Auth headers) in /etc/modsecurity/crs/crs-setup.conf.
4. Test API Authentication via cURL
Validate that the HTTP Authorization header reaches WordPress successfully using cURL in your terminal:
curl -i -X GET https://example.com/wp-json/wp/v2/users/me \
--user "your_username:xxxx xxxx xxxx xxxx"
A successful request returns HTTP/2 200 OK alongside your user JSON profile object.
Why This Fails for Some Users
- Non-HTTPS Connections: WordPress forcibly disables the Application Passwords feature on plain HTTP connections for security reasons unless explicitly overridden by
wp_is_application_passwords_available_dev_mode. - Basic Auth Collisions at the Server Level: If the server or directory is already protected by HTTP Basic Authentication via
.htpasswd, the web server consumes theAuthorizationheader before passing execution to PHP, stripping the Application Password payload. - PHP CGI/FastCGI Mode Stripping Headers: Older PHP-CGI installations drop authorization parameters under strict server security policies unless
CGIPassAuth OnorSetEnvIfrules are defined globally in master server configs rather than local.htaccessfiles. - User Permission Limitations: Application Passwords inherit the capabilities of the associated WordPress account. If the user account lacks
edit_postsor administrative REST API permissions, the endpoint returns a 401/403 status regardless of valid header transmission.