Expand my Community achievements bar.

Get ready! An upgraded Experience League Community experience is coming in January.
SOLVED

how to test my servlet via Javascript in localhost?

Avatar

Level 9

So in postman, I am sending using this header

2025-10-27 19_26_35-http___localhost_4502_bin_acara_principals_accessrequest.json - john-young-a0001.jpg

 

 

and this is working fine. (YW string is admin:admin encoded using base64).

 

I'm trying to do the same in javascript, but I keep on getting a 403.

headers.append('Content-Type', 'application/json');
if (window.location.host.indexOf('localhost') != -1) {
headers.append('Authorization', 'Basic YWRtaW46YWRtaW4=');
}
const response = await fetch(myUrl,
{
method: 'POST',
headers: headers,
body: payload
}
);


Any ideas on how it can be done? Thanks

1 Accepted Solution

Avatar

Correct answer by
Level 3

Hi @jayv25585659 ,

Here’s a quick way to make a POST request to your AEM endpoint using a pre-encoded Basic Auth token and a local CSRF bypass for testing.

const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Basic YWRtaW46YWRtaW4=', // pre-encoded token
  'CSRF-Token': 'nocheck' // for local testing
});

const res = await fetch('http://localhost:4502/bin/your/servlet/endpoint', {
  method: 'POST',
  headers,
  credentials: 'include',
  body: JSON.stringify(payload)
});

 

 Notes:
 Make sure payload is JSON.stringified.
credentials: 'include' sends cookies/session.
For production, replace 'nocheck' with a real CSRF token.

Thanks,

Lavish Vasuja

View solution in original post

4 Replies

Avatar

Level 2

Hi @jayv25585659, you can try configuring "Adobe Granite Cross-Origin Resource Sharing Policy" configuration to allow the domain from where JS calls occur.

Avatar

Community Advisor

Hi @jayv25585659,

Here’s what’s actually happening - Postman works because it’s not affected by browser security rules. But when you call your AEM servlet via JavaScript in a web page:

Basic Auth header is correct
Browser blocks the request -> 403 due to CORS / CSRF / Sling Referrer Filter

 

Add these headers:

const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", "Basic YWRtaW46YWRtaW4="); // admin:admin
headers.append("CSRF-Token", "nocheck"); // Important for POST in Author

Then:

const response = await fetch("http://localhost:4502/bin/acara/principals/accessrequest", {
  method: "POST",
  credentials: "include",
  headers: headers,
  body: JSON.stringify(payload)
});

For AEM Author only

You also need to whitelist your local site:

AEM -> Web Console ->

OSGi Config -> Adobe Granite Cross-Origin Resource Sharing Policy
Add:

Allowed Origins: http://localhost:3000 (or your front-end port)
Allowed Headers: Authorization, Content-Type, CSRF-Token
Supported Methods: POST, GET, OPTIONS

Also update:

Adobe Granite Referrer Filter
-> Add localhost to allow list

Quick Test to Confirm Your Servlet Works in Browser

Open browser DevTools:

fetch("http://localhost:4502/bin/acara/principals/accessrequest", {
    method: "POST",
    headers: {
        "Authorization": "Basic YWRtaW46YWRtaW4=",
        "Content-Type": "application/json",
        "CSRF-Token": "nocheck"
    },
    body: JSON.stringify({ test: true })
}).then(r => console.log(r.status, r.text()));

If this works -> CORS/Referrer are the missing pieces in your frontend app.


Santosh Sai

AEM BlogsLinkedIn


Avatar

Employee Advisor

 

Hi @jayv25585659 ,

This is a classic browser vs Postman issue. Postman skips browser security (no preflight/CORS and no enforced CSRF), so a request that works there can get 403 from the browser. Two things to check/fix:

1) CORS / preflight

  • Open DevTools → Network and look for the OPTIONS request (preflight).

  • If OPTIONS returns 4xx or is missing Access-Control-Allow-* headers, configure AEM to allow the origin, Authorization, Content-Type, CSRF-Token and the POST method.

  • Browser requires server to reply with these headers for the real POST to be allowed.

2) AEM CSRF protection (very common cause)

  • AEM often requires a CSRF token on POSTs. Postman may work without it; the browser will not.

  • Fetch the token and send it in CSRF-Token header before your POST.

Minimal flow (works cross-origin if CORS is allowed):

 

// Step 1: Fetch CSRF token
const getCsrfToken = async () => {
const response = await fetch('http://localhost:4502/libs/granite/csrf/token.json', {
credentials: 'include',
});

if (!response.ok) {
throw new Error(`Failed to fetch CSRF token: ${response.statusText}`);
}

const data = await response.json();
return data.token;
};

// Step 2: Send POST request with Basic Auth and CSRF token
const sendAccessRequest = async (payload) => {
const token = await getCsrfToken();

const response = await fetch('http://localhost:4502/bin/acara/principals/accessrequest.json', {
method: 'POST',
mode: 'cors', // required for cross-origin requests
credentials: 'include', // include cookies/session
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic YWRtaW46YWRtaW4=',
'CSRF-Token': token,
},
body: JSON.stringify(payload),
});

if (!response.ok) {
throw new Error(`Request failed: ${response.status} ${response.statusText}`);
}

return response.json();
};

// Example usage
try {
const payload = { /* your request body */ };
const result = await sendAccessRequest(payload);
console.log('Access request successful:', result);
} catch (error) {
console.error('Error:', error);
}

Hope this helps.

Regards,
Manvi Sharma

Avatar

Correct answer by
Level 3

Hi @jayv25585659 ,

Here’s a quick way to make a POST request to your AEM endpoint using a pre-encoded Basic Auth token and a local CSRF bypass for testing.

const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Basic YWRtaW46YWRtaW4=', // pre-encoded token
  'CSRF-Token': 'nocheck' // for local testing
});

const res = await fetch('http://localhost:4502/bin/your/servlet/endpoint', {
  method: 'POST',
  headers,
  credentials: 'include',
  body: JSON.stringify(payload)
});

 

 Notes:
 Make sure payload is JSON.stringified.
credentials: 'include' sends cookies/session.
For production, replace 'nocheck' with a real CSRF token.

Thanks,

Lavish Vasuja