Why does my http://localhost CORS origin not work?
Chrome does not support localhost for CORS requests (a bug opened in 2010, marked WontFix in 2014).
To get around this you can use a domain like localho.st
(which points at 127.0.0.1 just like localhost) or start chrome with the --disable-web-security
flag (assuming you're just testing).
Https not working for cors, but http://localhost is
The problem was with my server! Since I am using typescript I had to set up my package.json a certain way to build to heroku; However, for development purposes I changed my serve function from "node dist/index.js" to "nodemon dist/index.js" and rebuilt the project. I am using firebase for some other auth like functions that are in the frontend and thought because of that my backend was working fine but it was crashed. Turns out this was not a cors issue at all.
// ./Package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"engines": {
"node": "14.x"
},
"scripts": {
"build-ts": "tsc",
"postinstall": "npm run build-ts",
"start": "npm run serve",
"serve": "node dist/index.js",
"watch-node": "nodemon dist/index.js",
"watch-ts": "tsc -w"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/connect-mongodb-session": "^2.4.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-session": "^1.17.4",
"@types/node": "^17.0.21",
"nodemon": "^2.0.15",
"typescript": "^4.6.2"
},
"dependencies": {
"connect-mongodb-session": "^3.1.1",
"cors": "^2.8.5",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-session": "^1.17.2",
"firebase-admin": "^10.0.2",
"mongoose": "^6.2.4"
}
}
CORS error on localhost, Is that a normal?
Yes, because CORS doesn't care about localhost
in any specific way. Instead, the combination (!) of hostname and port is being used to differ between multiple parties.
Hence, for CORS, localhost:3000
is something completely different than localhost:8000
, so, yes, this is normal.
CORS - localhost as allowed origin in production
I'm assuming you have
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://localhost
The risk is that any services running on a user's machine could effectively bypass the Same Origin Policy for your site.
So if you have a REST URL such as
https://example.com/User/GetUserDetails
A malicious or compromised service running on the user's computer could make that request via the user's browser and then grab details about the user, because their authentication cookie will be passed with the request.
Now, you could argue that a malicious service running on the user's computer could just grab the authentication cookie from their browser directly and then make the request itself. However, if the service has some flaws of its own (say XSS), this could allow another site to compromise the user via your REST service (evil.example.org --XSS-> localhost -CORS-> example.com/User/GetUserDetails
).
Another scenario that could put you at risk if the user is running a local reverse proxy to access something. This would enable the target site to compromise the user through yours, should that target site be malicious or be compromised. This is because the user would be accessing the target site with a domain of localhost
.
If you really need to do this I suggest you have a special developer account for your REST service that when accessed adds the Access-Control-Allow-Origin: https://localhost
header to your requests only. That way, you are not putting other users at risk because you know you are only running the front-end server only at https://localhost
so you cannot be compromised by your open CORS setting.
Another way may be to use something like noonewouldusethis2859282.localhost
for your local copy of the front-end. Then you can safely add the Access-Control-Allow-Origin: https://noonewouldusethis2859282.localhost
header because nobody else would use this and would be safe from CORS attacks.
Origin origin is not allowed by Access-Control-Allow-Origin
Since they are running on different ports, they are different JavaScript origin
. It doesn't matter that they are on the same machine/hostname.
You need to enable CORS on the server (localhost:8080). Check out this site: http://enable-cors.org/
All you need to do is add an HTTP header to the server:
Access-Control-Allow-Origin: http://localhost:3000
Or, for simplicity:
Access-Control-Allow-Origin: *
Thought don't use "*" if your server is trying to set cookie and you use withCredentials = true
when responding to a credentialed request, server must specify a domain, and cannot use wild carding.
You can read more about withCredentials
here
Why can't I connect to localhost server from localhost client (cors error)?
Any malicious site can take advantage of your cookies stored in the system called Cross-site request forgery
Any browser tries to prevent you from these attacks so they disable CORS.
Shorthand Fix [Not recommended] : There are many plugins out there you can use for your local testing that disables these checks on browser.
Proper Fix: Use an Express middleware to apply Access-Control-Allow-Origin: *
in your header when response is returned back from the server.
Gist is that when browser sends the request to your server it will append Origin: http://localhost:3000
to the headers. Reacting to this request from browser, server should return a Access-Control-Allow-Origin header to specify which origins can access the server's resources.
You can be strict here to return Access-Control-Allow-Origin: http://localhost:4200
or open your gates by sending Access-Control-Allow-Origin: *
.
Here is the quick code to have an express middleware:
const express = require('express');
const request = require('request');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
app.get('/jokes/random', (req, res) => {
request(
{ url: 'https://joke-api-strict-cors.appspot.com/jokes/random' },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
res.json(JSON.parse(body));
}
)
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
Source: https://medium.com/@dtkatz/3-ways-to-fix-the-cors-error-and-how-access-control-allow-origin-works-d97d55946d9
P.S, this is a very good read for your understanding of CORS.
Chrome CORS error on request to localhost dev server from remote site
Original Answer
I finally found the answer, in this RFC about CORS-RFC1918 from a Chrome-team member. To sum it up, Chrome has implemented CORS-RFC1918, which prevents public network resources from requesting private-network resources - unless the public-network resource is secure (HTTPS) and the private-network resource provides appropriate (yet-undefined) CORS headers.
There's also a Chrome flag you can change to disable the new behavior for now:chrome://flags/#block-insecure-private-network-requests
Disabling that flag does mean you're re-opening the security hole that Chrome's new behavior is meant to close.
Update 2021: A few months after I posted this question, the flag I referenced in my original answer was removed, and instead of disabling a security feature I was forced to solve the problem more satisfactorily by serving assets over HTTPS.
Update 2022: Chrome 98 is out, and it introduces support for Preflight requests. According to the announcement, failed requests are supposed to produce a warning and have no other effect, but in my case they are full errors that break my development sites. So I had to add middleware to teach webpack-dev-server
how to serve preflight requests.
Private Network Access (formerly CORS-RFC1918) is a specification that forbids requests from less private network resources to more private network resources. Like HTTP to HTTPS, or a remote host to localhost.
The ultimate solution was to add a self-signed certificate and middleware which enabled requests from my remote dev server to my localhost webpack-dev-server
for assets.
Generate certificates
cd path/to/.ssl
npx mkcert create-cert
Configure webpack-dev-server
to use certificates and serve preflight requests
module.exports = {
//...
devServer: {
https: {
key: readFileSync("./.ssl/cert.key"),
cert: readFileSync("./.ssl/cert.crt"),
cacert: readFileSync("./.ssl/ca.crt"),
},
allowedHosts: ".example.dev", // should match host in origin below
setupMiddlewares(middlewares, devServer) {
// Serve OPTIONS requests
devServer.app.options('*', (req, res) => {
// Only serve if request has expected origin header
if (/^https:\/\/example\.dev$/.test(req.headers.origin)) {
res.set({
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Private-Network": "true",
// Using * results in error if request includes credentials
"Access-Control-Allow-Origin": req.headers.origin,
})
res.sendStatus(200)
}
}
return middlewares
}
}
}
Trust certificates
- Right click
ca.crt
in Windows Explorer and select Install Certificate - Select Current User.
- Choose Place all certificates in the following store, then Browse..., and select Trusted Root Certification Authorities.
- Finish.
Firefox-specific instructions
Firefox doesn't respect your authoritah! by default. Configure it to do so with these steps:
- Type
about:config
into the address bar - Search for
security.enterprise_roots.enabled
- Toggle the setting to
true
Cross origin requests are only supported for HTTP. error when loading a local file
My crystal ball says that you are loading the model using either file://
or C:/
, which stays true to the error message as they are not http://
So you can either install a webserver in your local PC or upload the model somewhere else and use jsonp
and change the url to http://example.com/path/to/model
Origin is defined in RFC-6454 as
...they have the same
scheme, host, and port. (See Section 4 for full details.)
So even though your file originates from the same host (localhost
), but as long as the scheme is different (http
/ file
), they are treated as different origin.
Related Topics
Why Split the ≪Script≫ Tag When Writing It With Document.Write()
How to Add Onload Event to a Div Element
Why Js Function Name Conflicts With Element Id
Remove CSS Class from Element With JavaScript (No Jquery)
How to Get the Entire Document HTML as a String
Double Quote in JavaScript String
Parsing Json Objects For HTML Table
(Change) VS (Ngmodelchange) in Angular
Using Queryselector With Ids That Are Numbers
Angularjs - Value Attribute on an Input Text Box Is Ignored When There Is a Ng-Model Used
Invoking JavaScript Code in an Iframe from the Parent Page
"Submit Is Not a Function" Error in JavaScript
Jquery Document.Createelement Equivalent
How to Implement "Select All" Check Box in Html
How to Get a File or Blob from an Object Url