Cant enable CORS on the server side NodeJS - javascript

I can't enable CORS on the server-side. My frontend and backend servers have different ports. Here is how server-side is implemented:
http
.createServer(function (req, res) {
// .. Here you can create your data response in a JSON format
// const { headers, method, url } = req;
// let body = [];
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// const responseBody = { headers, method, url, body: JSON.stringify(data) };
response.write('{asd: 123}'); // Write out the default response
res.end(); //end the response
})
.listen(port);
And I call the fetch function from the frontend-side like this one:
fetch('http://localhost:3035', {
method: 'POST',
mode: 'same-origin', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'include', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(line), // body data type must match "Content-Type" header
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.log(error));
But still getting errors:
Security Error: Content at http://localhost:3030/ may not load data from http://localhost:3035/.
TypeError: "NetworkError when attempting to fetch resource."

You explicitly disallowed CORS on the client side by setting mode: 'same-origin' instead of the default mode: 'cors'.
To quote the docs:
same-origin — If a request is made to another origin with this mode set, the result is simply an error. You could use this to ensure that a request is always being made to your origin.
Since http://localhost:3035/ is another origin than http://localhost:3030/, the result is, exactly as designed, "simply an error".
Set it to mode: 'cors' or remove mode entirely since cors is the default anyway.
On a side note, Access-Control-Request-Method is a request header in the preflight request, not a response header. You should remove it.
As mentioned in the comments: For a credentialed request to work, you cannot use an allowed origin of *. If you don't want to hardcode the expected origin at this point though, you can avoid this problem by always returning the origin that the current request comes from, using res.setHeader('Access-Control-Allow-Origin', req.headers.origin).

Related

how to do a post request with jession cookies (fetch/axios)? [duplicate]

I am trying out the new Fetch API but is having trouble with Cookies. Specifically, after a successful login, there is a Cookie header in future requests, but Fetch seems to ignore that headers, and all my requests made with Fetch is unauthorized.
Is it because Fetch is still not ready or Fetch does not work with Cookies?
I build my app with Webpack. I also use Fetch in React Native, which does not have the same issue.
Fetch does not use cookie by default. To enable cookie, do this:
fetch(url, {
credentials: "same-origin"
}).then(...).catch(...);
In addition to #Khanetor's answer, for those who are working with cross-origin requests: credentials: 'include'
Sample JSON fetch request:
fetch(url, {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
console.log('Gotcha');
}).catch((err) => {
console.log(err);
});
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
Have just solved. Just two f. days of brutforce
For me the secret was in following:
I called POST /api/auth and see that cookies were successfully received.
Then calling GET /api/users/ with credentials: 'include' and got 401 unauth, because of no cookies were sent with the request.
The KEY is to set credentials: 'include' for the first /api/auth call too.
If you are reading this in 2019, credentials: "same-origin" is the default value.
fetch(url).then
Programmatically overwriting Cookie header in browser side won't work.
In fetch documentation, Note that some names are forbidden. is mentioned. And Cookie happens to be one of the forbidden header names, which cannot be modified programmatically. Take the following code for example:
Executed in the Chrome DevTools console of page https://httpbin.org/, Cookie: 'xxx=yyy' will be ignored, and the browser will always send the value of document.cookie as the cookie if there is one.
If executed on a different origin, no cookie is sent.
fetch('https://httpbin.org/cookies', {
headers: {
Cookie: 'xxx=yyy'
}
}).then(response => response.json())
.then(data => console.log(JSON.stringify(data, null, 2)));
P.S. You can create a sample cookie foo=bar by opening https://httpbin.org/cookies/set/foo/bar in the chrome browser.
See Forbidden header name for details.
Just adding to the correct answers here for .net webapi2 users.
If you are using cors because your client site is served from a different address as your webapi then you need to also include SupportsCredentials=true on the server side configuration.
// Access-Control-Allow-Origin
// https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
This works for me:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
function headers(set_cookie=false) {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}
Then build your call:
export function fetchTests(user_id) {
return function (dispatch) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
user_id: user_id
}),
headers: headers(true)
};
return fetch('/api/v1/tests/listing/', data)
.then(response => response.json())
.then(json => dispatch(receiveTests(json)));
};
}
My issue was my cookie was set on a specific URL path (e.g., /auth), but I was fetching to a different path. I needed to set my cookie's path to /.
If it still doesn't work for you after fixing the credentials.
I also was using the :
credentials: "same-origin"
and it used to work, then it didn't anymore suddenly, after digging much I realized that I had change my website url to http://192.168.1.100 to test it in LAN, and that was the url which was being used to send the request, even though I was on http://localhost:3000.
So in conclusion, be sure that the domain of the page matches the domain of the fetch url.

React Native - I can't get a response from my FETCH, but my api does get the data i post

I tried many things, it will only POST to the api when it has "mode: no-cors" and no headers.
I am now trying with mode: 'cors', because i've read that i shouldn't use 'no-cors' because of security reasons. BUT, i do have to remove the headers or else it won't POST the data.
Here's the code:
signUp: async(email, password)=> {
let values = {
firstname: "pruebaNombre",
lastname: "pruebaApellido",
email: email,
password: password
}
const config = {
method: 'POST',
mode: 'cors',
// headers: {
// 'Access-Control-Allow-Origin':'*',
// 'Content-Type': 'application/json'
// },
body: JSON.stringify(values),
}
const response = await fetch('http://localhost/rest-api-authentication-example/API/create_user.php', config);
const data = await response.json();
console.log(data);
}
The console.log(data) should be a json with a message saying "user was created", but i get these errors:
Access to fetch at 'http://localhost/rest-api-authentication-example/API/create_user.php' from origin 'http://localhost:19006' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://localhost/rest-api-authentication-example/' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Failed to load resource: net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
The data does get posted on my server, but i can't get a the response from the fetch.
EDITED.- These are my headers on my server side:
header("Access-Control-Allow-Origin: http://localhost/rest-api-authentication-example/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
The 'Access-Control-Allow-Origin' header has a value 'http://localhost/rest-api-authentication-example/' that is not equal to the supplied origin
Try adding proxy: "http://localhost:${PORT}" to your React-Native package.json where PORT is your server port

Not sending correct header in netuno

I have a backend developed in netuno with api in java, and I want to send a pdf, I have no errors sending an excel, but for some reason I'm not getting it with pdf, my frontend is with react and redux.
The pdf is working when tested in postman (and yes, I know that in postman there are no cors problems),
In the browser if I send a corrupted pdf it is sent to the frontend but if the pdf has the right data it no longer passes in the cors.
I've already put the settings on the server side to receive the correct headers
_header.response.set('Access-Control-Allow-Origin', '*')
_header.response.set('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS')
_header.response.set('Access-Control-Allow-Headers', 'Content-Type, Expires, Cache-Control, must-revalidate, post-check=0, pre-check=0, Pragma')
_header.response.set('Access-Control-Allow-Credentials', 'true')
On the java side the pdf is going with the following headers
HttpServletResponse res = proteu.getServletResponse();
res.setHeader("Expires", "0");
res.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
res.setHeader("Pragma", "public");
res.setContentType("application/pdf");
res.setContentLength(baos.size());
OutputStream out = res.getOutputStream();
baos.writeTo(out);
out.flush();
out.close();
My fetch call is like this right now:
import fetch from "cross-fetch";
const FileSaver = require("file-saver");
const qs = require("qs");
fetch("myEndPoint", {
headers: {
accept: "application/pdf",
"content-type": "application/x-www-form-urlencoded"
},
referrerPolicy: "no-referrer-when-downgrade",
method: "POST",
mode: "no-cors",
body: qs.stringify({
...action.value
})
})
.then(resp => resp.blob())
.then(blob =>
FileSaver.saveAs(
blob,
"myPdf" +
new Date(Date.now())
.toLocaleString()
.replace(new RegExp("/", "g"), "")
.split(",")[0] +
".pdf"
)
);
when I execute the code in the browser, that's the way it is:
fetch("myEndPoint", {
credentials: "omit",
headers: { accept: "application/pdf", "content-type": "application/x-www-form-urlencoded", "sec-fetch-mode": "cors" },
referrer: "http://localhost:3000/foo",
referrerPolicy: "no-referrer-when-downgrade",
body:
"myData=foo",
method: "POST",
mode: "cors"
});
And I get the following error code:
Access to fetch at 'myEndPoint' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
which is strange, considering that all other calls work except this one, and the only difference is the type of document I get.
I have no error on the backend side.
why is chrome editing the mode: "no-cors" for "mode: "cors" ??
if I try to use "sec-fetch-mode: no-cors" in the fetch call header chrome answers:
Refused to set unsafe header "sec-fetch-mode"
The problem was in HttpServletResponse, when you use this on the netuno, it rewrites the header options, so I wasn't sending my previously configured settings, so the correct way to do this is as follows:
BaseService service = new BaseService(proteu, hili);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//my pdf code
service.getHeader().contentTypePDF();
service.getHeader().noCache();
service.getOut().write(baos.toByteArray());

why can't I set some headers on Request object?

I'm trying to request a rest API that needs authentication with a token. When constructing the Request object, some headers disappear.
Why can't I set my Authorization header ?
let http_headers = {
"Content-type": "application/json",
'Authorization': 'Token token='+my_token,
'Accept': 'Application/json'
};
let url = this.base_url + '/api/v1/test';
let init = {
method: "POST",
headers: new Headers(http_headers),
mode: 'no-cors',
credentials: 'omit' // I try that, but it doesn't seem to have effect
};
let req = new Request( url, init );
console.log(req.headers.get("Accept")); // Application/json
console.log(req.headers.get("Authorization")); // null, why ?
See the documentation for mode
no-cors — Prevents the method from being anything other than HEAD, GET or POST, and the headers from being anything other than simple headers. If any ServiceWorkers intercept these requests, they may not add or override any headers except for those that are simple headers. In addition, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues arising from leaking data across domains.
Set the mode to same-origin or cors to allow credentials to be set.
You probably want to use the fetch function and set the headers in the options parameter.
fetch(url, { //fetch options
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, cors, *same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// Your headers here
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
.then(); // parse response
Borrowed from https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
The fetch function returns a Promise that will have the Response object containing data from your api.

Send Authentication header with fetch or axios

How to send authentication header with fetch or axios ?
I have tried to do it but it on my client side haven't any header with Authentification value.
Here is my code example.
let myHeaders = new Headers();
myHeaders.append("Authorization", token);
myHeaders.append("Access-Control-Allow-Origin", "*");
myHeaders.append("Access-Control-Allow-Origin", "*");
let req = {
method: "GET",
headers: myHeaders,
mode: "no-cors",
credentials: "same-origin",
}
fetch('http://localhost:5000/secret', req)
.then(res => console.log(res))
.catch(err => console.log(err))
And I tried check it on my node.js code.
router.route("/").get(passportJWT, SecretController.secret);
For two origins to be considered "the same", they must share:
Scheme (e.g. https)
Hostname
Port
You are making a request from http://localhost:3000 to http://localhost:5000 so are making a cross-origin request.
credentials: "same-origin"
… but you've restricted credentials (like Authorization) to same-origin requests.
mode: "no-cors",
To send credentials with a cross-origin request, you must have permission via CORS.
You must not set no-cors.
You need
mode: "cors",
credentials: "include"

Categories

Resources