Category: API Integration / n8n Workflows
Tags:n8n,WordPress REST API,Application Passwords,Nginx,Apache,Basic Auth,FastCGI,DevOps
Author: Ayman Abdel-Halim
Difficulty: Intermediate
Estimated Reading Time: 12 minutes
📌 Executive Summary (TL;DR)
💡 From the Field (Ayman’s Engineering Log): “While deploying an automated content syndication and multi-site publishing pipeline in n8n, my post-creation nodes abruptly failed with 401 Unauthorized (rest_not_logged_in). I regenerated Application Passwords four times, verified user capabilities, and tested SSL handshakes, yet n8n was stubbornly rejected. A live packet inspection revealed the real culprit: Nginx FastCGI silently strips the HTTP Authorization header by default before passing the request to PHP-FPM. Adding a single fastcgi_param directive restored immediate communication. Here is the exact field-tested blueprint to diagnose and fix this in under 5 minutes.” — Ayman Abdel-Halim
Automating WordPress publishing via n8n, Python scripts, or external webhooks is one of the most reliable ways to build autonomous content pipelines. WordPress core ships with native support for Application Passwords (introduced in version 5.6), allowing developers to authenticate REST API requests via HTTP Basic Auth without exposing primary user credentials.
However, when connecting n8n to a self-hosted WordPress instance running on an Ubuntu VPS, Nginx, or Apache, you will almost invariably encounter this frustrating roadblock:
{
"code": "rest_not_logged_in",
"message": "You are not currently logged in.",
"data": {
"status": 401
}
}
In 95% of cases, your password is not wrong. Instead, your web server reverse proxy (Nginx or Apache) is aggressively dropping the HTTP Authorization header before it reaches WordPress core. In this comprehensive guide, we dissect the architectural root causes of this failure, provide bulletproof web server configurations, unpack n8n credential nuances, and show you how to verify your pipeline with terminal precision.
🔍 Why WordPress REST API Fails with 401 in n8n
To understand why this error happens, we must examine how HTTP Basic Authentication travels from n8n to WordPress core:
flowchart LR
A["n8n Webhook / Node"] -- "1. HTTP POST with Authorization Header" --> B["Nginx / Apache Reverse Proxy"]
B -- "2. Strips Header by Default (Security Scrubbing)" --> C["PHP-FPM Worker Pool"]
C -- "3. Passes Request WITHOUT Auth Header" --> D["WordPress Core REST Server"]
D -- "4. determine_current_user() finds NO credentials" --> E["HTTP 401 rest_not_logged_in"]
style B fill:#fee2e2,stroke:#ef4444,stroke-width:2px
style E fill:#fef2f2,stroke:#dc2626,stroke-width:2px
When n8n initiates a request to /wp-json/wp/v2/posts, it encodes your WordPress username and Application Password into an HTTP Basic Auth header:
POST /wp-json/wp/v2/posts HTTP/1.1
Host: devfix.pro
Authorization: Basic YXltYW5fYm90OmtaM2EgOGQ5TCBwUTFtIHZSNHg=
Content-Type: application/json
When this request hits your server, three distinct choke points can drop or invalidate that header:
┌────────────────────────────────────────────────────────────────────────┐
│ WordPress REST API 401 Failure Taxonomy │
├──────────────────────┬────────────────────────────────┬────────────────┤
│ Choke Point │ Mechanism of Failure │ Resolution │
├──────────────────────┼────────────────────────────────┼────────────────┤
│ Nginx FastCGI Proxy │ Missing fastcgi_param for auth │ Add param to │
│ │ headers in site server block │ fastcgi config │
├──────────────────────┼────────────────────────────────┼────────────────┤
│ Apache mod_rewrite │ Drops Authorization header on │ Add E-flag │
│ │ URL rewriting / permalinks │ to .htaccess │
├──────────────────────┼────────────────────────────────┼────────────────┤
│ HTTP Redirect (301) │ Trailing slash mismatch strips │ Fix n8n URL │
│ │ headers during redirect │ trailing slash │
├──────────────────────┼────────────────────────────────┼────────────────┤
│ WAF & Plugins │ Wordfence or Cloudflare blocks │ Whitelist n8n │
│ │ REST Basic Auth payloads │ IP / Endpoints │
└──────────────────────┴────────────────────────────────┴────────────────┘
🛠️ Fix 1: Configure Nginx FastCGI to Pass Authorization Headers
If your WordPress site is hosted on Nginx with PHP-FPM (the standard production stack on DigitalOcean, Linode, AWS EC2, or Hetzner), Nginx strips the Authorization header by default unless explicitly instructed to pass it.
Step 1: Open Your Site’s Nginx Configuration
Connect to your server via SSH and edit your domain’s virtual host block:
sudo nano /etc/nginx/sites-available/devfix.pro
# Or if using RunCloud / WordOps / EasyEngine:
# sudo nano /etc/nginx/conf.d/devfix.pro.conf
Step 2: Add the HTTP_AUTHORIZATION Parameter
Locate the location ~ \.php$ block that forwards execution to PHP-FPM, and ensure the fastcgi_param HTTP_AUTHORIZATION $http_authorization; directive is present:
server {
server_name devfix.pro www.devfix.pro;
root /var/www/devfix.pro/htdocs;
index index.php index.html;
# Standard WordPress Permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP-FPM Processing Block
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# =============================================================
# CRITICAL FIX: Pass Authorization Header to PHP-FPM
# =============================================================
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
fastcgi_pass_request_headers on;
}
}
Alternatively, if you manage multiple WordPress sites on the same VPS, you can add this directive globally across all sites by appending it directly to /etc/nginx/fastcgi_params:
echo "fastcgi_param HTTP_AUTHORIZATION \$http_authorization;" | sudo tee -a /etc/nginx/fastcgi_params
Step 3: Test and Reload Nginx
Always validate your configuration syntax before restarting the service to prevent server downtime:
sudo nginx -t
# Output must show: syntax is ok and test is successful
sudo systemctl reload nginx
⚙️ Fix 2: Configure Apache & .htaccess Rules
If your WordPress instance runs on Apache (or OpenLiteSpeed / cPanel), Apache’s URL rewrite engine (mod_rewrite) removes the Authorization header when rewriting requests to index.php.
Add the Authorization Flag to .htaccess
Open the .htaccess file located in your WordPress root directory (/var/www/html/.htaccess):
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# =============================================================
# CRITICAL FIX: Preserve HTTP Authorization Header for REST API
# =============================================================
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
If your Apache server runs with mod_proxy_fcgi, also add this directive to your main Apache configuration or virtual host:
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
🔑 Fix 3: WordPress Application Password Nuances & Formatting
WordPress Application Passwords have specific generation and formatting behaviors that catch developers off guard:
- Handling Spaces: When you generate an Application Password in Users > Profile, WordPress displays it grouped in four 4-character blocks separated by spaces (e.g.,
kZ3a 8d9L pQ1m vR4x).
While WordPress core can parse the password with or without spaces, certain HTTP libraries and n8n nodes fail if spaces are URL-encoded as%20. Best practice: Strip the spaces in n8n and usekZ3a8d9LpQ1mvR4x. - Username vs. Display Name: Always use the account’s User Login (the internal username created during registration), NOT the “Display name publicly as” or nickname. The REST API validates strictly against
user_login. - User Role Capabilities: The authenticated user must have at least the
EditororAdministratorrole to publish posts. An account with theAuthororContributorrole will return anHTTP 403 Forbidden (rest_cannot_create)when attempting to publish or assign categories.
🌐 Fix 4: Prevent Trailing Slash Header Dropping (HTTP 301 Redirects)
One of the most insidious causes of the 401 error in n8n is an unexpected HTTP 301 Moved Permanently redirect.
WordPress permalink structures enforce strict trailing slash rules. If your n8n node requests:
POST https://devfix.pro/wp-json/wp/v2/posts
Certain WordPress configurations or Nginx rewrite rules will respond with a 301 Redirect to:
https://devfix.pro/wp-json/wp/v2/posts/
By RFC specification, when an HTTP client follows a 301 redirect, it drops the Authorization header to prevent leaking credentials to external destinations. As a result, the redirected request arrives at WordPress completely unauthenticated, triggering the 401 error.
/posts/ works while /posts fails, your server is issuing a silent 301 redirect.🧩 Fix 5: Cloudflare WAF, Bot Fight Mode & Security Plugins
Even if Nginx and Apache are configured flawlessly, security layers sitting between n8n and WordPress can intercept and block REST requests:
1. Cloudflare Bot Fight Mode
If your domain is proxied through Cloudflare (orange cloud), Bot Fight Mode monitors incoming POST requests. Because n8n identifies itself with an automated User-Agent header (or no browser cookies), Cloudflare intercepts the request and issues a JavaScript challenge or Captcha, returning an HTTP 403 or 401.
Fix: In Cloudflare Dashboard > Security > WAF > Custom Rules, create a bypass rule:
- Expression:
(http.request.uri.path contains "/wp-json/wp/v2/" and ip.src eq 185.225.x.x)(Replace with your n8n server IP) - Action: Skip > All remaining WAF rules
2. Wordfence Security Plugin
Wordfence includes a specific setting that disables Application Passwords entirely to reduce brute-force attacks:
- Navigate to Wordfence > All Options > Brute Force Protection.
- Ensure that “Disable WordPress Application Passwords” is UNCHECKED.
- If Wordfence blocks n8n calls, go to Live Traffic, locate the blocked request from n8n, and click “Whitelist Param”.
💻 Step-by-Step n8n Setup: 2 Working Methods
Method A: Using the Native n8n WordPress Node
The native n8n WordPress node is the simplest way to interact with the API:
- Add a WordPress node to your canvas.
- Select Credential for WordPress API > Create New Credential.
- Enter your configuration:
- URL:
https://devfix.pro(Do not add/wp-jsonhere; n8n appends the path automatically). - Username: Your WordPress login username.
- Password: The generated Application Password (e.g.
kZ3a8d9LpQ1mvR4x).
- URL:
- Set Resource to
Postand Operation toCreate.
Method B: Using the Generic HTTP Request Node (Advanced Control)
When creating complex multi-category posts, custom taxonomies, or ACF fields, the generic HTTP Request node provides full raw payload control:
{
"nodes": [
{
"parameters": {
"method": "POST",
"url": "https://devfix.pro/wp-json/wp/v2/posts",
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"title\": \"{{ $json.title }}\",\n \"content\": \"{{ $json.html_content }}\",\n \"status\": \"publish\",\n \"categories\": [14, 22]\n}",
"options": {
"allowUnauthorizedCerts": false,
"timeout": 30000
}
},
"id": "c3e9821a-4f51-4e2b-a8f1-8f4350ef91a2",
"name": "Publish to WordPress REST API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [480, 240],
"credentials": {
"httpBasicAuth": {
"id": "wp-prod-auth",
"name": "DevFix WP Application Password"
}
}
}
]
}
📸 Live Production Verification & Telemetry
Below is the real-time execution log from our cloud server terminal demonstrating the immediate diagnosis, Nginx FastCGI configuration reload, and the successful n8n automated post-creation returning HTTP 201 Created:

Verifying with curl from Terminal
You can verify whether your server is passing headers properly before testing inside n8n using this terminal command:
curl -i -X POST "https://devfix.pro/wp-json/wp/v2/posts" \
-u "ayman_bot:kZ3a 8d9L pQ1m vR4x" \
-H "Content-Type: application/json" \
-d '{"title":"Authentication Diagnostics Test","status":"draft"}'
If successful, the server immediately returns HTTP/2 201 Created along with the newly created post ID and draft status payload.
🛡️ Security & Production Best Practices
Automating REST API calls requires strict adherence to the principle of least privilege:
• Never Use the Main Administrator Account: Create a dedicated WordPress user (e.g. api_publisher) assigned exclusively to the Editor role. If the credentials ever leak, an attacker cannot modify plugin files, alter themes, or compromise server settings.
• Sanitize Your Workflow Exports: If you export n8n workflows for backups or GitHub version control, ensure that Application Passwords and internal domain URLs are completely sanitized. Follow our step-by-step engineering tutorial: How to Strip API Keys and Sanitize n8n Workflows for Public Export.
• Stream Large Media Assets Independently: If your automation publishes heavy featured images or PDF attachments, avoid buffering large files in n8n RAM. Learn how to stream assets with flat memory usage in our companion guide: Building a Resilient Bulk Downloader in Python (Zero Memory Leaks).
• Audit Active Application Passwords: Regularly visit Users > Profile in WordPress. WordPress logs the Last Used timestamp and IP for every Application Password, allowing you to identify and revoke inactive tokens immediately.
❓ Frequently Asked Questions (FAQ)
Can I use my standard WordPress account password in n8n?
No. For security reasons, WordPress core disables HTTP Basic Auth with standard passwords on the REST API to protect against credential interception and brute-force attacks. You must generate a dedicated Application Password under your user profile.
Why does my n8n workflow work locally on localhost but fail on my VPS?
Local development environments (like LocalWP, Docker, or XAMPP) often run Apache or PHP’s built-in development server where Authorization headers are passed automatically without proxy filtering. Production VPS setups enforce Nginx or reverse-proxy security layers that drop the header unless configured explicitly.
Do spaces in WordPress Application Passwords matter?
Core WordPress strips spaces during evaluation, so abcd efgh ijkl mnop and abcdefghijklmnop evaluate identically. However, some HTTP libraries (including certain versions of Axios or cURL wrappers) URL-encode spaces into %20, causing authentication failures. We recommend stripping spaces in your n8n credentials.
What if I am using OpenLiteSpeed instead of Nginx?
On OpenLiteSpeed (or CyberPanel), navigate to Server Configuration > External Application and ensure that Pass Through HTTP Headers is set to Yes, or add RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] inside your vHost rewrite rules.
Written by Ayman Abdel-Halim, AI Automation & Integration Developer at DevFix Pro.
1 thought on “Fixing 401 Unauthorized in WordPress REST API with n8n and Application Passwords”