CORS issue in Node/Express if we remove www prefix - node.js

We have a NodeJS/Express server that loads an HTML5 game we have stored on service outside of our server (think Amazon S3). The game must talk to our stats backend still on our NodeJS/Express server, but since it's on a different domain from the game that's running we encountered CORS issues. We fixed this by using the Node cors module and doing this with our route:
router.put("/stats/", cors(), async (req, res) => {
...
All has been fine, but we just learned if you visit our website WITHOUT the www prefix it still gives a CORS issue. As in if you visit us at www.example.com everything works, the game loads, and it can report stats back. But if you visit us at example.com then the game still loads, but it's giving this error:
Access to XMLHttpRequest at 'https://www.example.com/api/stats/' from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
From what I understand, how we're using the cors package it should enable all cors requests on that route. So why is it blocking this one?

Well no one ever responded, but we've managed to solve this just by using a 301 hostname redirect. Still not sure why CORS isn't working, but this fixes our specific issue.

If you are using cors lib from nodejs.
You can make a configuration for cors to support both domains.
As an example:
const cors = require('cors')
//cors config
app.use(cors({
origin: ['https://example.com', 'https://www.example.com']
methods: "GET, POST, PUT, DELETE",
optionsSuccessStatus:200,
credentials: true
}))

Related

Node.JS OvernightJS Express CORS XMLHttpRequest has been blocked by CORS policy

I have an API developed in Node.JS, Typescript listening to localhost:3001
I have a frontend app in Angular, Typescript, listening to localhost:4200
I am trying to upload an image file using ngx-image-cropper, converting it to base64, from frontend to the API.
When the PATCH (update) http request is sent to the API, I get:
Access to XMLHttpRequest at 'http://localhost:3001/member/10' from origin 'http://localhost:4200' has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
My Overnight.JS Express server is configured as below:
const corsOpts1 = { origin: '*' };
this.app.use(
cors(corsOpts1)
);
}
I have tried several things, no success.
For example, on top of my class controller, I added the directive ClassMiddleware as below:
#Controller('member')
#ClassMiddleware([cors()])
That's the response looking at Chrome's dev tools:
I have run out of options. My extensive research on the internet did not provide me with a successful solution.
I'd appreciate if some who had this issue before, how did you solve it. Many thanks.
Looks like your front-end is doing a Pre-Flight cors request. Try using the following on your express server:
app.options('*', cors()) // include before other routes
See the express docs for more information (scroll down to Enabling CORS Pre-Flight).

Access to XMLHttpRequest at '...' from origin 'localhost:3000' has been blocked by CORS policy

Edit
A little late, but I remember that I ended up solving this issue by setting credentials: true in my cors config on my backend.
By complete accident, I noticed that if I set credentials: false in my axios client on the frontend, everything worked fine. However, switching it to true kept throwing the error. I then put two and two together and set credentials: true on my backend and everything worked as expected.
My app used cookies, so it had to be done this way.
This may be a duplicate, but I havent found a thread relating specifically to my issue.
I am making the following API call:
const config = {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS"
}
};
const {
data: { ip }
} = await axios.get("https://api.ipify.org?format=json", config);
And this throws an error:
Access to XMLHttpRequest at 'https://api.ipify.org/?format=json' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
When I deploy my app to Heroku, the API call works as expected. However it does not work when developing on my local machine. Not sure what I'm missing here.
if you are building your rest api in nodejs. Follow the folowing simple steps
Stop the Node.js server.
npm install cors --save
Add following lines to your server.js or index.js
var cors = require('cors')
app.use(cors()) // Use this after the variable declaration
Now try to make your api call on the client side and it should work
After many days finally I got a solution . Instead of using CORS simply like this
const cors = require('cors');
app.use(cors());
in your server index.js using CORS option will solve the issue and now you can pass cookies or other credentials
const cors = require('cors');
const corsOptions ={
origin:'http://localhost:3000',
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
app.use(cors(corsOptions));
You can't really fetch data from servers, with a different hostname, that don't have a CORS policy to allow request from your domain.
In simpler words, localhost can't call ipify.org unless it allows it. It seems like it doesn't, and I assume that server is not managed by you. So your only option is to go with a reverse proxy. You can read how to create an http proxy with node here.
What you need is for your app to be served on a fake/stubbed host, rather than localhost:
local.development.ipify.org -> proxies to localhost:3000
That way, when you make your api call, you are under the same domain as ipify.org, and you won't get any CORS issues.
This article solved my problem in no time.
The quickest fix you can make is to install the moesif CORS extension . Once installed, click it in your browser to activate the extension. Make sure the icon’s label goes from “off” to “on“
First of all in your back-end app like express app you have to enable cors
like :
install cors running the command npm i cors
then go to your server.js or app.js or index.js file and add
var cors = require('cors');
app.use(cors())
3.cors will enable your client or front-end app to access your back-end routes. finally go to your routes and inside get route paste the following lines
router.get("/", (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*")
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Max-Age", "1800");
res.setHeader("Access-Control-Allow-Headers", "content-type");
res.setHeader( "Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, PATCH, OPTIONS" );
});
`
I also suffered for 2 hours facing this issue and i resolved my problem like this.So hope this will help you
Go to your package.json file and add:
"proxy": "your-api-url" but only the beginning/base, as an example if you are using the pokemon api, you just have to set "proxy" : "https://pokeapi.co/api/v2"
and in your service file you can use axios with the path you need:
axios.get("/pokemon?limit=1000")
.then(response => {
resolve(response.data.results);
})
What you seem to be trying to do is telling the server that it should use the CORS policies that you have specified in your Axios call. This is simply not how things work - the server defines its own CORS policies, and you simply must conform to them. If the server that you are trying to access does not support http://localhost:3000 in its CORS policies, you cannot use that origin with the API.
If the server is yours, look into the cors package and configure it to allow localhost:3000as an origin. If you do not own the server, you can't really change any CORS policies without asking the server owner if they would be willing to do so.
This may be due to the POST request from react app in development mode. You can bypass the CORS policy in development mode by the adding following line of code in your ' file.
{
...
"proxy": "http://localhost:3000",
...
}
There may be problem with the sequence of the
app.use(corse())
you should use it before defining routes
Use below codes in your server.js or app.js or index.js file of your backend
import cors from "cors";
const corsOrigin ={
origin:'http://localhost:3000', //or whatever port your frontend is using
credentials:true,
optionSuccessStatus:200
}
app.use(cors(corsOrigin));
I was getting this issue only on crome browser and on crome browser I had multilogin extension. When I delete this extension, this issue is fixed.
always double check and make sure you're not missing a trailing slash "/" in your front-end
if that didn't solve it, you'd want to try installing CORS to you back-end by first,
pipenv install django-cors-headers
then, inside the settings add corsheaders to the installed apps as well as corsheaders.middleware.CorsMiddleware to the Middleware; if your computer didn't already.
last but not least, make sure to add CORS_ORIGIN_ALLOW_ALL = True after the ALLOWED_HOSTS.
i hope this helped (first question ever answered btw)
You have to use res.setHeader with your response
res.setHeader("Access-Control-Allow-Origin", "*")
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Max-Age", "1800");
res.setHeader("Access-Control-Allow-Headers", "content-type");
Had this issue when sending post request from reactjs app to a django api that I manage. Solved it by installing django-cors-headers, adding core headers to installed apps, adding core headers middleware, and lastly adding the react host domain 'http://localhost:3000' into the CORS_ORIGIN_WHITELIST inside of the django settings file.
After this, my react app was able to get responses from the django api.
try to use fetch instead of Axios
return fetch(
url +
"?" +
new URLSearchParams({
email: email,
}),
{
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
mode: "no-cors",
}
);
If you're using axios, check out the package version.
I faced same issue when using version 1.1.x.
After change to 1.2.x, issue resolved.
"axios": "^1.2.3",

CORS-enabled server not denying requests

I am trying to use express Cors with my resitfy server and it doesn't seem to be denying requests coming from other ips. I am working locally so I tried setting origin to a random public ip but all of my requests are still going through
Here is my route:
module.exports = function(app) {
var user = require('./controllers/userController');
var cors = require('cors');
var corsOptions = require('./cors.json');
app.post('/auth/signup', cors(corsOptions),user.createUser);
app.post('/auth/login', cors(corsOptions), user.validateUser);
app.post('/auth/generateKeys', cors(corsOptions), user.generateKeys);
app.post('/auth/generateToken', user.generateToken);
};
and here is my cors.json file where I have set a random ip:
{
"origin": "http://172.16.12.123",
"optionsSuccessStatus": 200,
}
With cors set on the route I can see the following in postman but the request is still going through? I would expect an access denied response.
Access-Control-Allow-Origin →http://172.16.12.123
CORS configuration on its own isn’t going to cause a server to deny requests. You can’t cause server-side blocking of requests just through CORS configuration.
The only thing servers do differently when you configure CORS support is just to send the Access-Control-Allow-Origin response header and other CORS response headers. That’s it.
Actual enforcement of cross-origin restrictions is done only by browsers, not by servers.
So no matter what server-side CORS configuration you make to a server, the server still goes on accepting requests from all clients and origins it would otherwise; in other words, all clients from all origins still keep on getting responses from the server just as they would otherwise.
But browsers will only expose responses from cross-origin requests to frontend JavaScript code running at a particular origin if the server the request was sent to opts-in to permitting the request by responding with an Access-Control-Allow-Origin header that allows that origin.
That’s the only thing you can do using CORS config. You can’t make a server only accept and respond to requests from particular origins just by doing any server-side CORS configuration. To do that, you need to use something other than just CORS configuration.
CORS does not prevent anyone from sending GET or POST requests to your application or exposed API URL.
Instead, it indicates to the web browser that AJAX requests are allowed to this server, from the domain they are executed.
But only AJAX requests executed from a domain are CORS-controlled. Entering the URL in the web browser will not activate CORS: it is not a firewall.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
The order of event is:
Domain A executes AJAX on User's browser to request API URL on Domain B
User's browser sends a basic primary request to target Domain B and checks if CORS are allowed for Domain A
If allowed, AJAX request is executed otherwise null is returned

No 'Access-Control-Allow-Origin'

I am requesting an image from Cloudfront CDN. each time I make a request from the client I am getting this error:
Access to Image at https://cdn.mywebsite/image.png from origin
http://localhost:5000 has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin http://localhost:5000 is therefore not allowed
access. The response had HTTP status code 403.
I'm using express for the server and have added the following to allow Access but still no luck..
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', "*");
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
})
Any Advice would be much appreciated!
==========================================================================
Update
Hi #jfriend00
So what my goal is to serve protected content over CF CDN.
For this I am sending signed Cookies to the client using the following module below.
var cf = require('aws-cloudfront-sign')
var options = {keypairId: 'keypairId', privateKeyPath: '/foo/bar'}
var signedCookies = cf.getSignedCookies('https://cdn.mywebsite.com/*', options);
for(var cookieId in signedCookies) {
res.cookie(cookieId, signedCookies[cookieId]);
}
Then I am simply making a request from the client to the cdn to fetch the image with:
<img src="https://cdn.mywebsite.com/image.png" crossorigin="anonymous" alt="test picture">
At this point the Access-Control-Allow-Origin error is displayed in the console.
Note:
var signedUrl = cf.getSignedUrl('https://cdn.mywebsite.com/image.png', options)
This signedUrl works when directly accessing it but not if I make the request from localhost or the website it self.
CORS headers have to be on the server that is serving the resource. So, if the resource that you are getting the CORS error on is https://cdn.mywebsite/image.png, then that's the host that has to allows CORS access. You can't fix that by allowing CORS on localhost.
FYI, it seems odd that you are getting a CORS error when accessing an image. If you use <img> tag for the access, then the <img> tag will not be subject to same origin restrictions. The same origin restrictions apply to Ajax calls made from browser Javascript.
I also not that you appear to be mixing http and https in the same page which can also cause issues.
Are you trying to download the image with Ajax? Please show your client code that is causing this error and explain what you are trying to accomplish and perhaps we can offer a different solution.

I'm getting a CORS error although Access-Control-Allow-Credentials is not set

I wrote a server app with node.js and express. The app uses the cors node package for POST requests with origin "*" because I need to be able to post from mobile apps.
Here is how CORS is enabled in the app:
var cors = require('cors');
var app = express();
app.configure(function() {
app.use(cors());
});
When I try to POST a request from a browser, I get this error:
XMLHttpRequest cannot load url. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'null' is therefore not allowed access.
However, I don't see any Access-Control-Allow-Credentials header in the response. Here is the failing request and the response in Chrome's network tab:
Why does it complain about the credentials flag?
We finally solved this. Here are our findings and the train of thought that led us to the solution:
The CORS issue happened only with POST, not GET.
The CORS issue happened only when I made the request from a local HTML whose URL starts with file://. There was no issue when I requested it from http://localhost.
When initiating a POST request from the file:// protocol, the origin is null. Turns out that the issue was that null is not covered by the wildcard *.
Setting Allow-Access-Control-Origin to null was not enough, because apparently a request from origin null includes credentials, so I had to set Allow-Access-Control-Credentials to true.
So here is my updated server code that accepts POST requests from any source, including a web view in a mobile app that works with file://:
var cors = require('cors');
var app = express();
app.configure(function() {
app.use(cors({ origin: 'null', credentials: true }));
});

Resources