In my node.js server I have included CORS as middleware like so:
app.use(cors({ origin: 'http://<CORRECT_ORIGIN_URL>:3030', credentials: true }))
I'm using Apollo Client in the app that sends the request, and have set credentials to 'include' when initialising ApolloClient, like so:
// Create a WebSocket link
const wsLink = process.browser ? new WebSocketLink({
uri: `ws://<CORRECT_REQUEST_URL>:8000/graphql`,
options: {
reconnect: true,
},
}) : null
// Create an http link (use batch, allow cookies response from server)
const httpLink = new BatchHttpLink({
uri: 'http://<CORRECT_REQUEST_URL>/api/',
credentials: 'include'
})
// Split terminating link for websocket and http requests
const terminatingLink = process.browser ? split(
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
httpLink,
) : httpLink
// Create Apollo client
const client = new ApolloClient({
link: ApolloLink.from([authLink, errorLink, terminatingLink])
})
When I attempt to sign-in, I can see that a preflight OPTIONS request is sent and gets the correct response back:
Request Headers (OPTIONS request)
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://<CORRECT_ORIGIN_URL>:3030
Referer: http://<CORRECT_ORIGIN_URL>/login
Response Headers (OPTIONS request)
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: http://<CORRECT_ORIGIN_URL>:3030
Connection: keep-alive
Content-Length: 0
Date: Wed, 20 Mar 2019 03:09:14 GMT
Server: nginx/1.15.5 (Ubuntu)
Vary: Origin, Access-Control-Request-Headers
X-Powered-By: Express
Yet when the actual POST request is sent, I get the following response:
Response Headers (POST request)
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Wed, 20 Mar 2019 03:09:15 GMT
Server: nginx/1.15.5 (Ubuntu)
Transfer-Encoding: chunked
Vary: Accept-Encoding, Origin
X-Powered-By: Express
I have no idea why the response headers are different in the post request when the options preflight show that it should be correct.
This incorrect POST response leads to the following error message on the client:
Access to fetch at 'http://<CORRECT_REQUEST_URL/api/' from origin
'http://<CORRECT_ORIGIN_URL>:3030' 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'.
I've tried googling and searching stackoverflow for a solution but can't find anything. Any ideas?
A CORS preflight OPTIONS request can be triggered just by adding a Content-Type header to a request — if the value's anything except application/x-www-form-urlencoded , text/plain , or multipart/form-data .
A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers. It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method , Access-Control-Request-Headers , and the Origin header.
I solved my problem.
The issue is that Apollo Server adds CORS middleware by default, which was overriding my CORS settings. From Apollo's documentation:
Provide false to remove CORS middleware entirely, or true to use your middleware's default configuration.
The default value is true.
To solve the issue, I simply had to disable CORS functionality in Apollo, which simply required setting cors: false
in .applyMiddleware like so:
server.applyMiddleware({
app,
path: '/',
cors: false,
});
Further reference:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With