React fetch, “credentials: include”, breaks my entire request and I get an error

旧巷老猫 提交于 2021-01-23 06:41:49

问题


Summary:

I'm doing a fetch request in React to my Node.js server.

Whenever I do NOT include credentials: "include" and in my fetch request, the request is successfully made to the server and returned to the client.

However, when I do include credentials: "include", like the below:

fetch('http://localhost:8000/',
    {   method: "GET", 
       'credentials': 'include',
        headers: new Headers({
            'Accept': 'application/json',
            'Access-Control-Allow-Origin':'http://localhost:3000/',
            'Content-Type': 'application/json',
    })

}) ....

I get this preflight error:

login:1 Access to fetch at 'http://localhost:8000/' from origin 'http://localhost:3000' has been blocked by CORS policy: 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'.

Context:


Why do I need to include either of those?

  1. I think it's obvious why I need to include the "headers", I'm using cors and if I don't include 'Access-Control-Allow-Origin':'http://localhost:3000/' then the server will not accept the request.
  2. Why do I need to include the "credentials" if it works without it? Because if I do not include "credentials" while the fetch request executes correctly, the session cookie will not be sent to the server from my client UNLESS I include credentials: "include". If I delete all the headers and include mode: 'no-cors', then the fetch request executes and the session cookie is sent to the server, but obviously I get an opaque response, and I need to be using cors anyways.

Attempts:


There are a lot of stack overflow questions SIMILAR to this, but not exact, thus their solutions don't work.

Here are some things I have tried that didn't work:

  1. This is already on my server, but someone suggested trying it on the client side so I did: 'Access-Control-Request-Method': 'GET, POST, DELETE, PUT, OPTIONS',

  2. 'Access-Control-Allow-Credentials': 'true',

  3. 'withCredentials': 'true',

  4. Origin: 'http://localhost:3000/auth',

  5. crossorigin: true,

  6. And yes, I've already set up a proxy (which helped solve a prior issue) as such: "proxy": "http://localhost:8000"

  7. I've tried many more other solutions to no avail, I'm certain I've read, if not all, the vast majority of all questions relating to do with this issue and the corresponding answers. My server is setup correctly, which is why I didn't include any code from it.

In an ideal world I wouldn't need to use credentials: "include" for the session cookie to be sent back to my server, but that is the cause of another solution I had to implement.

If anyone could help me, I would be very grateful.

TLDR:


My preflight request does pass whenever I do NOT include credentials: "include", but the session cookie is not passed.

The session cookie is passed when I do include credentials: "include" and mode: 'no-cors', however, I receive an opaque response and I need to use cors.

Finally, when I combine the two (cors and credentials), I my preflight request fails with the below error:

login:1 Access to fetch at 'http://localhost:8000/' from origin 'http://localhost:3000' has been blocked by CORS policy: 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'.


回答1:


this most likely comes from your server. Do you have cors npm package installed in the backend ?

https://www.npmjs.com/package/cors

You will need ton configure it aswell.

Most likely in your index.js file.

const express = require("express")
const cors = require("cors");
const app = express();

app.use(cors({
  origin : http://localhost:3000 (Whatever your frontend url is) 
  credentials: true, // <= Accept credentials (cookies) sent by the client
})

app.use("/api/whatever/the/endpoint", yourRouter);

This has to be set before any route. Origin can be an array of whitelisted (allowed) domains to communicate with your backend api.




回答2:


If you want to accept requests from multiple different domains you could do something like this also:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

As documented here: https://www.zigpoll.com/blog/cors-with-express-and-fetch



来源:https://stackoverflow.com/questions/63351799/react-fetch-credentials-include-breaks-my-entire-request-and-i-get-an-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!