Cross-Origin Request Blocked in any browser eventhough supported - rest

I have already read a lot of other stackoverflow questions and github issues but none were able to resolve my issue so i decided to open a new one.
I am building a short application with Nextjs (frontend) and Express+Node (backend). Everytime the Frontend makes a get/post request to the backend via REST I get
"Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at DOMAIN. (Reason: CORS header
'Access-Control-Allow-Origin' missing)."
To fix this, i tried multiple things. First of all i added app.use(cors()) in my backend, but that didnt work. I added
const configcors = {
origin: true,
methods: 'GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE,PATCH',
allowedHeaders: 'X-Powered-By,Content-Type,Content-Length,ETag,Date,Connection,Keep-Alive',
exposedHeaders: 'X-Powered-By,Content-Type,Content-Length,ETag,Date,Connection,Keep-Alive',
credentials: true
}
app.use(cors(configcors))
to allow absolutely everything but that didnt work either. i tried to add the headers manually using
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
which - as you might expect - didnt work either.
Lastly i thought if maybe there was an error with the preflight, so i tried
app.options('*', cors(configcors))
which didnt work either. Furthermore, trying to solve the problem, i looked at the network tab, to identify the headers and whether the correct headers were send. In Firefox there appeared no Request in the Networking Tab at all.
Chrome:
On chrome tho, i can see the request but there are no response headers at all. This let me assume that maybe CORS wasnt the problem - To try this i installed the moesif CORS extension in chrome to allow all sorts of CORS. I was wrong: with the extension enabled, every request works perfectly fine - but i cant rely on an extension in production.
This means that the error definitely has something to do with CORS but I have no idea what I should do now.
if anyone had similiar troubles i would be very thankful for your advice.

Try this:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "*");
next();
});

Related

Why is the Fetch API not working on my machine? [duplicate]

My Chrome Extension performs a get request which works fine. Because testing is faster with snippets, I want to do the exact same thing in the Chrome Console or in the Chrome Snippets. Minimal example:
fetch(url, {
method: "GET"
}).then(response => response.text())
.then(html => console.log(html))
.catch(error => console.log(error))
Unfortunately, there I only get
TypeError: Failed to fetch for the error and
Failed to load resource: net::ERR_FAILED in Chrome's inline error marker
In my Chrome Extension I ran into a CORS issue so what I did in my AWS Lambda function was to set the headers to
const headers = {
'Content-Type': 'application/json',
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
};
so I suppose CORS isn't the problem here. But I can't seem to figure out as to what differences it could make to have the requests run in the Extension vs. in the console/snippets. What could I be missing here?
I also do not see the request in AWS CloudWatch so I suppose it doesn't even leave my machine. I am testing on a Chrome User that has 0 extensions installed, same happens in incognito
To circle out any issues with my server I have also inserted the examples from https://lockevn.medium.com/snippet-to-fetch-remote-rest-api-and-display-in-console-of-chrome-devtool-6896a7cd6041
async function testGet() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
console.log(await response.json())
}
async function testPost() {
let r = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
lockevn: 1
}),
})
console.log(await r.json())
}
testGet()
testPost()
Chrome's Network tab shows the request as stalled
The linked 'explanation' gives
Queueing: The browser queues requests when:
There are higher priority requests.
There are already six TCP connections open for this origin, which is
the limit. Applies to HTTP/1.0 and HTTP/1.1 only.
The browser is briefly allocating space in the disk cache
Stalled: The request could be stalled for any of the reasons described in Queueing.
Higher priority seems odd, 6 connections can't be the issue either since I have restarted my browser before testing, and the disk cache issue doesn't sound like the problem either. I'm not macOS with no anti virus
I managed to find the issue. In order to avoid potentially privileging my requests by opening the Chrome Developer Console in my AWS dashboard tab, I have created a new tab (chrome://new-tab-page/) and performed the requests in the console. This returned the errors described.
When I have updated my question with the example code I wanted to confirm if it was running before asking someone to try it if it works on their machine. For quick runtime-validation I opened the Console in the Stackoverflow tab and it worked. I only wanted to check if the code can be interpreted but it turned out to actually return a result. The same is valid for my AWS instance, if I run it on a https website it works fine. No idea why this is not documented but "disk cache" is mentioned as a potential error.
tldr don't open Chrome Console in new tab for requests in the console, use any website. This may have to do with CORS headers only working if the request doesn't have empty headers to begin with maybe (?)
I specifically avoided using a website console instance for testing because I wanted to prevent potential cookies on the AWS page from doing something that someone else couldn't do on their machine. Good thinking bad result haha
Thank you so much for your comments suggesting the help, much appreciated.

axios causing an unintended OPTIONS request on HERE Autocomplete api

I am getting a preflight error 405: Method not allowed from the HERE API when I request autocomplete as per the documentation.
UPDATE 2:
I have since determined that Axios was adding my default.common authentication headers from my app's API client onto the HERE API client. Axios is supposed to keep those defaults separate per-client, but it seems that it doesn't ... at least not the version I have. I replaced the defaults with a per-client request interceptor and it worked fine. The request no longer triggers an OPTION pre-flight. No issue with HERE's API other than that it doesn't support OPTION method.
UPDATE:
The reason it fails is because HERE does not support the OPTIONS method, only the GET. So now the question is: Why does axios trigger an OPTIONS request when I don't set any headers? An XMLHttpRequest() based GET request does not trigger OPTIONS for the same URL. Something is happening with axios but I don't know what and I can't seem to investigate the headers that axios is sending.
ORIGINAL:
I've tried to find information about this error, as well as HTTP vs HTTPS. I haven't seen others having this problem so I feel like I must be making a simple error. The URL is generated correctly because it works when pasted directly into the browser for example.
const hereClient = axios.create({
baseURL: 'https://autocomplete.geocoder.api.here.com/6.2/'
})
async function searchHere (query) {
let searchTerms = query.split(' ').join('+')
let result = await hereClient.get('suggest.json', {
params: {
app_id: '<APPID>',
app_code: '<APPCODE>',
query: searchTerms
}
})
return processHereSearchResults(result.data)
}
The GET request fails on the OPTION preflight with a 405: Method not allowed. But if I paste the generated URL into a browser then it returns the expected results. For example:
https://autocomplete.geocoder.api.here.com/6.2/suggest.json?app_id=APPID&app_code=APPCODE&query=8131
returns:
{"suggestions":[{"label":"Česko, Brandýs nad Orlicí, 3123","language":"cs","countryCode":"CZE","locationId":"N . . .
Same result whether http or https.
I have since determined that Axios was adding my default.common authentication headers from my app's API client onto the HERE API client. Axios is supposed to keep those defaults separate per-client, but it seems that it doesn't ... at least not the version I have. I replaced the default header setting with a per-client request interceptor to set my authentication and it worked fine. The request no longer triggers an OPTION pre-flight. No issue with HERE's API other than that it doesn't support OPTION method.

Odd CORS error querying JIRA REST API [duplicate]

This question already has answers here:
Origin is not allowed by Access-Control-Allow-Origin
(18 answers)
Closed 6 years ago.
I am trying to develop a D3 visualisation project for our JIRA boards, but I've fallen at the first hurdle. I'm having trouble authenticating and getting a list of JIRA boards.
This code is entirely client-side and is in Angular 2 RC 3. My service looks like this:
public authenticate( username:string, password:string ):void {
let encodedAuth:string = window.btoa( `${username}:${password}` );
this.headers = new Headers();
this.headers.append( 'Content-Type', 'application/json' );
this.headers.append( 'Authorization', `Basic ${encodedAuth}` );
}
public getAllBoards():Observable<Boards> {
return this.http.get( `http://${this.host}/rest/agile/1.0/board`, this.headers )
.map( response => response.json() as Boards )
}
and the code in my component looks like this:
constructor( protected jiraService:JIRAService ) {
this.jiraService.authenticate('me#you.com', 'password');
this.jiraService.getAllBoards().subscribe(
boards => this.boards = boards
);
}
Unfortunately, this generates what looks like a CORS error in my browser:
XMLHttpRequest cannot load https://myjira.atlassian.net/rest/agile/1.0/board. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 401.
...which is a little unexpected. This same URL in the browser works fine. Examining the request in Charles I see the error "SSL Proxying not enabled for this host: enable in Proxy Settings, SSL locations", but cannot actually find this setting. I don't care if I can't see it in Charles actually, I just want to get it working!
I have tried several of the npm JIRA packages but none of them are remarkable and seem to be designed for server-side development.
Any help greatly appreciated.
You get this error when you access it from within an application that was initially loaded from a different URL. If you load a new page from this "other" URL then this is not a CORS situation because the initial page load is already from this URL.
The server need to provide the expected CORS headers for the browser to allow this request. This is not an Angular issue but only a server issue.
Workarounds are
JSONP (doesn't support custom headers)
provide support server-side where your Angular application calls to your server which then forwards to the other server and then forwards the response it gets to your Angular application.

Angular/Node/Express/Passport - Issues when connecting to facebook(CORS)

i'm trying to use facebook authentication on my NodeJs server. i came to the tutorial of http://scotch.io/ and have it working locally when using a REST client(Postman, etc).
To improve the UI i used Angular JS as a front end. but when i call a http.get to my specific route given on the NodeJs back-end i get the following error in chome and firefox:
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…0%2Fapi%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=3000000000006. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost:8080' is therefore not allowed access.
i've tried several solutions on StackOverflow but its still not working...
my NodeJs uses Express 4.* and a CORS middleware.
for Angular i found several ways to enable CORS, none working so far.
I hope you can help me:D Thanks in advance!
You can use 'window.location="http://localhost:3000/auth/facebook"'; in your Angular Controller from where you send the request to your Express Server which contains passport.authenticate stuff.
This will stop your angular to call facebook auth dialogue page as AJAX request.
It works for me!
I'm using Angular with Node/Express as well, and the following function works for me with my own backend services (I'm currently not using it with Facebook to be honest), so just check it out:
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Access-Control-Allow-Origin');
res.header("Access-Control-Max-Age", "86400"); // 24 hours
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
};
Then, you need to use it tin the app.confiure()method as follows:
// configure Express
app.configure(function() {
app.use(allowCrossDomain);
...
});
It's important to use it BEFORE all other directrives!

restler 3 cross domain not working

My restler 3 api works fine on local test server and works fine on production server if calls from that same server, but if I make the call remotely then it fails.
Using the same rest client with the luracast online examples it works fine with remote call so must be something in my configuration (either my api or my production server).
I found mention of need to send headers and so tried adding these headers to index.php file:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, PATCH, DELETE');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: *');
But that didn't help. Using RESTClient addon in firefox, I can see that those headers are sent, and the browser will show the data both locally and remotely, whether I use those header commands or not.
Here's a sample call:
https://api.masterpiecesolutions.org/v1/artists/?key=A4oxMOYEUSF9lwyeFuleug==
My index.php for that call uses this, with 2nd param to map to root level
$r->addAPIClass('Artists', '');
Don't know if that is relevant.
Also, the production server is Amazon EC2, so perhaps has something to do with security policy?
Or, maybe it's some other header issue? In google chrome, using Advanced Rest Client extension, it gives status of 403 Forbidden and Content-Type is text/plain (whether using local or remote server) so it won't work at all, unlike the firefox addon.
I also see use of $_SERVER['HTTP_ORIGIN'] in Restler.php, and this doesn't appear to be supported everywhere yet?
* is not a valid value for the Access-Control-Allow-Headers response header. You need to list out every non-simple request header. For example:
header('Access-Control-Allow-Headers: Content-Type');
Also consider putting a single origin value or just * for the Access-Control-Allow-Origin header. I just visited your sample url and there are multiple values in that header. Although this should work according to the CORS spec, it is not very widely adopted yet.
Lastly I noticed that the server was setting Access-Control-Allow-Credentials: true. If you set this to true, then you also need to do two other things:
The value of the Access-Control-Allow-Origin header must be the value of the Origin (e.g. http://localhost, it can not be *).
You will need to set xhr.withCredentials = true; in your JavaScript client code.
If you are just testing, you should try to get things working without setting the Access-Control-Allow-Credentials header. It will make things easier to debug.
The problem, for me at least, was using SSL and the restclient class didn't accommodate that.
So I added (to my RestClient.class.php from phpclasses.org)
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // for SSL
and now it works.
Also required was setting
public static $crossOriginResourceSharing = true;
in Defaults.php for Restler 3.