Express CORs policy preventing Apollo client from fetching from server

Viewed 5657

I'm running a react dev server on http://localhost:3000 and an express server on http://localhost:8080 and am using an Apollo Client to query the server. To enable session data to be passed from client to server I have added the credentials: "include" parameter when initializing the Apollo Client.

I've added the following line in my express server (before the routes are defined) to configure cors:

app.use(cors({ credentials: true, origin: "http://localhost:3000" }));

However, when executing queries, the following error is thrown:

Access to fetch at 'http://localhost:8080/graphql' from origin 'http://localhost:3000' 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'.

Why is the header response showing up as *? Am I configuring CORs incorrectly or am I missing something else?

3 Answers

The problem I was running into here was that despite enabling CORS for express:

app.use(cors({ credentials: true, origin: "http://localhost:3000" }));

The GraphQL middleware was over-riding the setting. Make sure to pass the cors: false param as shown below if using an Apollo Server and associated middleware.

gqlServer.applyMiddleware({ app, path: "/graphql", cors: false });

This error is a CORS error generated by the browser. use npm install --save http-proxy-middleware in your front end and add setupProxy.js file in frontend/src/setupProxy.js

setupProxy.js

//run defferent ports for website and api server 
const proxy = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(proxy('/api/', { target: 'http://localhost:8080/' })); //make change as per your application (So you can access your data on  http://localhost:8080/api/ )
};

Alternate solution

If you are using webpack dev server, here's another way to proxy requests without making changes on NodeJS. Adding this to package.json:

  "proxy": "http://localhost:8080"

Should allow webpack to proxy requests made to http://localhost:3000 to http://localhost:8080.

But this would mean request will need to be made to http://localhost:3000 instead of http://localhost:8080.

Since you have credentials: true, you should include the credentials in your fetch call:

fetch(url, {
  credentials: 'include'  
})

or

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true); 
xhr.withCredentials = true; 
xhr.send(null);

This will send the request with the headers set to Access-Control-Allow-Credentials: true

without this, it will be rejected.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials

Related