WordPress CORS Issue with Bearer Token in POST Requests

I’m having trouble sending POST requests with Authorization: Bearer <token> headers to my WordPress site. The issue seems to be server-related since everything works perfectly in Postman.

My Setup

I’m running MAMP Pro with a WordPress site that has a custom API (not the default WordPress REST API).

The Process

  1. Login request from client-app.com/auth.html to server-api.com/v1/login with credentials.
  2. Get back a JWT token named accessToken.
  3. Send data from client-app.com/dashboard.html to server-api.com/v1/notifications with form data and Authorization: Bearer <accessToken> header.

Login Code (Step 1):

const BASE_URL = "https://server-api.com";
const LOGIN_ENDPOINT = "v1/login";
const NOTIFICATION_ENDPOINT = "v1/notifications";
const HTTP_METHOD = "POST";

return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open(HTTP_METHOD, BASE_URL + "/" + LOGIN_ENDPOINT);
    xhr.onload = () => resolve(xhr.response);
    xhr.onerror = () => reject(xhr.response);
    xhr.send(loginData);
});

Protected Request Code (Step 3):

return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open(HTTP_METHOD, BASE_URL + "/" + NOTIFICATION_ENDPOINT);
    xhr.setRequestHeader('Authorization', "Bearer " + TokenService.getAccessToken());
    xhr.onload = () => resolve(xhr.status);
    xhr.onerror = () => reject(xhr.status);
    xhr.send(notificationData);
});

The Problem

Step 1 works fine everywhere. Step 3 works in Postman but fails the preflight OPTIONS request in the browser. I tested with a third-party mock API and it worked, so I think it’s my server config.

What I’ve Tried

  • Added rewrite rules to MAMP virtual host and .htaccess.
  • Removed Authorization header (request works without it).
  • Set different Content-Type headers.
  • Added trailing slashes to endpoints.
  • Various SetEnvIf configurations.

I’m stuck and think either Apache is blocking Authorization headers or WordPress is interfering with CORS. Any ideas?

Had the same problem with WordPress APIs and Bearer tokens. Apache wasn’t handling the Authorization header right for cross-origin requests. I added Header always set Access-Control-Allow-Headers "Authorization, Content-Type" to my .htaccess file, but the real fix was handling OPTIONS preflight requests in my WordPress plugin. WordPress doesn’t automatically send back the right CORS headers for OPTIONS requests when you’re using custom auth. You need to add a handler in your API that catches OPTIONS requests and returns proper CORS headers before WordPress even touches the request. Fixed my preflight failures completely.

Classic MAMP Apache issue - I’ve hit this before. MAMP strips Authorization headers during preflight requests even when your main endpoint works fine. Check if mod_rewrite is messing with the Authorization header in your MAMP Apache config. Adding RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] to your virtual host fixed it for me. Also check if WordPress security plugins are blocking cross-origin Authorization headers. Wordfence and similar plugins love blocking Bearer tokens from different domains. Try disabling security plugins temporarily to see if that kills the preflight issue.

check your MAMP PHP version - some versions dont pass auth headers to WP right. had the same issue, switching from PHP 7.4 to 8.1 fixed my bearer token preflight problems. also dont forget to add CGIPassAuth On to your Apache config if u haven’t already.