I have a setup involving
Frontend server (Node.js, domain: localhost:3000) <---> Backend (Django, Ajax, domain: localhost:8000)
Browser <-- webapp <-- Node.js (Serve the app)
Browser (webapp) --> Ajax --> Django(Serve ajax POST requests)
Now, my problem here is with CORS setup which the webapp uses to make Ajax calls to the backend server. In chrome, I keep getting
Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.
doesn't work on firefox either.
My Node.js setup is:
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:8000/');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
};
And in Django I'm using this middleware along with this
The webapp makes requests as such:
$.ajax({
type: "POST",
url: 'http://localhost:8000/blah',
data: {},
xhrFields: {
withCredentials: true
},
crossDomain: true,
dataType: 'json',
success: successHandler
});
So, the request headers that the webapp sends looks like:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE'
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=***; sessionid="***"
And here's the response header:
Access-Control-Allow-Headers: Content-Type,*
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Type: application/json
Where am I going wrong?!
Edit 1: I've been using chrome --disable-web-security, but now want things to actually work.
Edit 2: Answer:
So, solution for me django-cors-headers config:
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000' # Here was the problem indeed and it has to be http://localhost:3000, not http://localhost:3000/
)
This is a part of security, you cannot do that. If you want to allow credentials then your Access-Control-Allow-Origin must not use *. You will have to specify the exact protocol + domain + port. For reference see these questions :
Access-Control-Allow-Origin wildcard subdomains, ports and protocols
Cross Origin Resource Sharing with Credentials
Besides * is too permissive and would defeat use of credentials. So set http://localhost:3000 or http://localhost:8000 as the allow origin header.
If you are using CORS middleware and you want to send withCredential boolean true, you can configure CORS like this:
var cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));
Expanding on #Renaud idea, cors now provides a very easy way of doing this:
From cors official documentation found here:
"
origin: Configures the Access-Control-Allow-Origin CORS header.
Possible values:
Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS.
"
Hence we simply do the following:
const app = express();
const corsConfig = {
credentials: true,
origin: true,
};
app.use(cors(corsConfig));
Lastly I think it is worth mentioning that there are use cases where we would want to allow cross origin requests from anyone; for example, when building a public REST API.
try it:
const cors = require('cors')
const corsOptions = {
origin: 'http://localhost:4200',
credentials: true,
}
app.use(cors(corsOptions));
If you are using express you can use the cors package to allow CORS like so instead of writing your middleware;
var express = require('express')
, cors = require('cors')
, app = express();
app.use(cors());
app.get(function(req,res){
res.send('hello');
});
If you want to allow all origins and keep credentials true, this worked for me:
app.use(cors({
origin: function(origin, callback){
return callback(null, true);
},
optionsSuccessStatus: 200,
credentials: true
}));
This works for me in development but I can't advise that in production, it's just a different way of getting the job done that hasn't been mentioned yet but probably not the best. Anyway here goes:
You can get the origin from the request, then use that in the response header. Here's how it looks in express:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', req.header('origin') );
next();
});
I don't know what that would look like with your python setup but that should be easy to translate.
(Edit) The previously recomended add-on is not available any longer, you may try this other one
For development purposes in Chrome, installing
this add on will get rid of that specific error:
Access to XMLHttpRequest at 'http://192.168.1.42:8080/sockjs-node/info?t=1546163388687'
from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the
'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
when the request's credentials mode is 'include'. The credentials mode of requests
initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
After installing, make sure you add your url pattern to the Intercepted URLs by clicking on the AddOn's (CORS, green or red) icon and filling the appropriate textbox. An example URL pattern to add here that will work with http://localhost:8080 would be: *://*
Though we have many solutions regarding the cors origin, I think I may add some missing part. Generally using cors middlware in node.js serves maximum purpose like different http methods (get, post, put, delete).
But there are use cases like sending cookie response, we need to enable credentials as true inside the cors middleware Or we can't set cookie. Also there are use cases to give access to all the origin. in that case, we should use,
{credentials: true, origin: true}
For specific origin, we need to specify the origin name,
{credential: true, origin: "http://localhost:3000"}
For multiple origins,
{credential: true, origin: ["http://localhost:3000", "http://localhost:3001" ]}
In some cases we may need multiple origin to be allowed. One use case is allowing developers only. To have this dynamic whitelisting, we may use this kind of function
const whitelist = ['http://developer1.com', 'http://developer2.com']
const corsOptions = {
origin: (origin, callback) => {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error())
}
}
}
Had this problem with angular, using an auth interceptor to edit the header, before the request gets executed. We used an api-token for authentification, so i had credentials enabled. now, it seems it is not neccessary/allowed anymore
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = req.clone({
//withCredentials: true, //not needed anymore
setHeaders: {
'Content-Type' : 'application/json',
'API-TOKEN' : 'xxx'
},
});
return next.handle(req);
}
Besides that, there is no side effects right now.
CORS ERROR With NETLIFY and HEROKU
Actually, if none of the above solutions worked for you then you might wanna try this.
In my case, the backend was running on Heroku and the frontend was hosted on netlify.
in the .env file, of the frontend, the server_url was written as
REACT_APP_server_url = "https://ci-cd-backend.herokuapp.com"
and in the backend, all my api calls where written as,
app.get('/login', (req, res, err) => {});
So, Only change you need to do is, add /api at the end of the routes,
so, frontend base url will look like,
REACT_APP_server_url = "https://ci-cd-backend.herokuapp.com/api"
and backend apis should be written as,
app.get('/api/login', (req, res, err) => {})
This worked in my case, and I believe this problem is specifically related when the front end is hosted on netlify.
We deployed our nodejs app to aws ,but it is giving this error while accessing any api,
Access to XMLHttpRequest at 'https://vkluy41ib9.execute-api.ap-south-1.amazonaws.com/dev/api/auth/login' from origin 'https://cmc-app.netlify.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Now the issue if our node app is hosted on localhost its working fine but deploying on live server its throwing error
this is our code :
app.options(cors());
app.use(function (req, res, next) {
//Enabling CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, x-client-key, x-client-token, x-client-secret, Authorization"
);
next();
})
If you want to use cors() then you need to write:
app.options("*", cors());
otherwise it will not be registered correctly. Using this method, the handler returned from cors() will be used on all OPTIONS-requests.
The second part where you do app.use is not necessary, because it does nearly the same as the method before.
To get the result you wanted with the second part, you could write:
app.options("*", cors({
methods: ["GET", "HEAD", "OPTIONS", "POST", "PUT"],
allowedHeaders: ["origin", "X-Requested-With", "Content-Type", "Accept", "x-client-key", "x-client-token", "x-client-secret", "Authorization"]
}));
All configuration options for cors are listed here: https://www.npmjs.com/package/cors#configuration-options
When sending a request over CORS from my React app to my Node.JS and Express.js backend i get an:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3001/students/login. (Reason: CORS preflight channel did not succeed).
Im using axios for sending out requests and this is the request configuration:
({ email, password }) => {
return axios.post(API_ENDPOINT + UCENIK.post.login,
{ email, password },
{
withCredentials: true,
Headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
})
}
I have tried allowing CORS in Express with these headers:
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization')");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
next();
});
Edit: fixed using npm Cors module and providing this object for settings:
{
origin: 'http://localhost:3000',
cors: true
}
I assume this is only a development problem, because your express instance and reactjs frontend server run on a different port. In the production environment this probably isn't the case.
In stead of using CORS in your development cycle try to proxy the request from your frontend server to your express server.
For exmple the webpack devserver has a seperate proxy configuration https://webpack.js.org/configuration/dev-server/#devserver-proxy
I have a project that sends HTTP requests from the client using Axios
axios.create({
baseURL: `http://localhost:8081/`,
withCredentials: true
})
And I suppose this allows cookies -Which I am sure it shows in the browser before you ask- to be sent with the requests.
The problem occurs in the back-end, when this error shows in the log:
Response to preflight request doesn't pass access control check: The
value of the 'Access-Control-Allow-Origin' header in the response must
not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://localhost:8080' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
I tried this:
app.use(cors({
//origin : to be set later
credentials: true,
}))
and this instead:
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, Authorization");
res.header("Access-Control-Allow-Credentials", true);
next();
});
but neither seems to work.
EDIT - Here is the answer for future visitors
With the help of the participants in comments, I found out I had to set the origin value:
app.use(cors({
origin : "http://localhost:8080",
credentials: true,
}))
I know it's too late for OP, but for those who keep comming here - what helped me is:
app.use(cors({
preflightContinue: true,
credentials: true,
}));
source: https://expressjs.com/en/resources/middleware/cors.html
I got this problem and I fixed it by setting the header "Access-Control-Allow-Origin" to the URL of my frontend instead of "*"
More details: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
I have a AngularJS and NodeJS (API) application.
I had already enabled CORS on my NodeJS using CORS() nodejs library.
I included the required headers to enable CORS too.
I am having CORS issue only when I access the website from my company computer. It Works fine from my personal computers. Can anyone please guide me on what I am doing wrong. Any help or suggestion please.
Chrome Console Logs:
-------------------- Headers ---------------------
General:
Request URL:www.example.com:81/api/getdata
Request Method:GET
Status Code:503 Service Unavailable
Remote Address:111.111.11.111:81
Response Headers:
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:close
Content-Length:973
Content-Type:text/html; charset=UTF-8
Expires:Thu, 01 Jan 1970 00:00:00 GMT
P3P:CP="CAO PSA OUR"
Pragma:no-cache
Request Headers:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:www.example.com:81
Origin:http://www.example.com
Referer:http://www.example.com/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
-------------------- Response: --------------------
<html>
<head>
<title>Web Page Blocked</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<meta name="viewport" content="initial-scale=1.0">
</head>
<body bgcolor="#e7e8e9">
<div id="content">
<h1>Web Page Blocked</h1>
<p>Access to the web page you were trying to visit has been blocked in accordance with company policy. Please contact your
system administrator if you believe this is in error.</p>
<p><b>User:</b> </p>
<p><b>URL:</b> www.example.com:81/api/getdata </p>
<p><b>Category:</b> unknown </p>
</div>
</body>
</html>
Browser Console Error:
XMLHttpRequest cannot load http://www.example.com:81/api/getdata. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://www.example.com' is therefore not allowed
access. The response had HTTP status code 503.
------ EDIT -----
Here is the cors() I am passing.
app.options('*',cors());
app.use(function (req, res, next){
res.header("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,Content-type, Accept");
res.header("Access-Control-Allow-Credentials", true);
next();
});
It's either a problem with your company firewall or a CORS problem.
Try to accept every origin in CORS module :
var express = require('express');
var cors = require('cors')
var app = express();
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.get('/products/:id', cors(corsOptions), function(req, res, next){
res.json({msg: 'This is CORS-enabled for every origin.'});
});
app.listen(80, function(){
console.log('CORS-enabled web server listening on port 80');
});
Now you should receive response headers like this :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
If it still does not work, then port 81 must be blocked.
Another possibility is that the proxy of your company removes or blocks some headers which could explain why Access-Control-Allow-Origin: www.example.com is not present in your response headers