I use on back-end nodejs(nestjs). From the server i send the cookies after login:
res.cookie('token', 'token', {
httpOnly: true
});
And this is my cors setting app.enableCors({credentials: true });;
As front-end i use reactjs. After login the server sent the cookies here:
But i need to get the cookies here:
Why i don't get the cookies in the place where i showed and how to get them there to save them even o reloading the page?
The reason the cookie is not persisted in the frontend is that you are probably not setting the withCredentials on your frontend request. An example with axios would be:
axios.post('http://localhost:3001', {}, { withCredentials: true })
An example with fetch is:
fetch(url, {
method,
headers: {
'Content-Type': 'application/json'
},
credentials: 'include'
}
Note: For security reasons you must have explicitly specified the origin on your backend CORS configuration otherwise you will get the following error:
Access to XMLHttpRequest at 'http://localhost:3001/' 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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
To do that with nest.js/express you can pass:
app.enableCors({
credentials: true,
origin: ['http://localhost:3002', 'your-production-domain']
});
Related
This question already has an answer here:
How to correctly configure server and browser to avoid cors errors? Fetch API + Node.js
(1 answer)
Closed 2 years ago.
I'm using the cors library and have the following settings on my server (running on localhost:8000):
cors({
// Allow requests from these origins :: Access-Control-Allow-Origin
origin: `http://localhost:8001`,
// Allow certain headers :: Access-Control-Allow-Headers
allowedHeaders: [
"Origin",
"X-Requested-With",
"Content-Type",
"Accept",
"Authorization"
],
// Allows us to send cookies cross origin :: Access-Control-Allow-Credentials
credentials: true,
// Allow this method
methods: "GET"
});
This works fine when I make a request like this:
fetch('http://localhost:8000/api/test', { method: 'GET', credentials: 'include', mode: 'cors' })
But I get a CORS error in the console when I add headers to the request:
fetch('http://localhost:8000/api/test', { method: 'GET', credentials: 'include', mode: 'cors', headers: { 'Content-Type': 'application/json' })
The Error I'm getting in Chrome is:
Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:8001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
The only difference is that I added a Content-Type header, but I would expect this to work because its in my list of allowedHeaders
origin: `http:localhost:3001`,
It seems wrong, back slashes (//) are missing. Otherwise your sample looks good and it works if I create a simple server with your sample.
If it still does not work, you can try to clear the cache. There was an issue in github: https://github.com/expressjs/cors/issues/159
Server is on http://localhost:3001, and client is same, but with port 3000.
On client I run simple fetch, I need to get logged-in user data from server, and currently I am doing it just using GET method(GET, POST, none work) like this(I also have to include cookies):
fetch("http://localhost:3001/user", {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json"
}
}).then(response => {
console.log(response);
});
And the server:
const cors = require("cors");
var corsOptions = {
origin: "http://localhost:3000",
optionsSuccessStatus: 200
};
app.get("/user", cors(corsOptions), function(req, res, next) {
u_session = req.session;
const db_result = db
.collection("users")
.findOne({ email: u_session.email }, function(err, result) {
if (err) throw err;
res.json({ email: result.email, type: result.type });
});
});
What I get is cors error:
Access to fetch at 'http://localhost:3001/user' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Also if i go to server URL through browser, I can see access-allow-control-allow-origin header set successfully.
Also as requested, screenshot of failed case network tab:
I've searched plenty of solutions on the internet, nothing seems to work. Am I missing something?
Thanks for any help.
Ensure that if you have a proxy set that it is set to http://localhost:3001. After that adjust your fetch to only use a partial url like so:
fetch("/user", {
method: "GET",
headers: {
"Content-Type": "application/json"
}
}).then(response => {
console.log(response);
});
it should be safe to remove this as well:
const cors = require("cors");
var corsOptions = {
origin: "http://localhost:3000",
optionsSuccessStatus: 200
};
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What sticks out to me is "preflight". I think it may be the OPTIONS request that doesn't have the correct CORS headers enabled. Ensure that you're enabling CORS on GET, POST, OPTIONS, and any other method your API supports.
Since you send credentials from the client, you must configure your cors module to allow credentials via athecredentials property. Also, application/json is a non-simple Content-Type, so you must allow that explicitly via allowedHeaders:
var corsOptions = {
origin: "http://localhost:3000",
optionsSuccessStatus: 200,
credentials: true,
allowedHeaders: ["Content-Type"]
};
Without this, the server will not include a Access-Control-Allow-Credentials header in the OPTIONS preflight, and the browser will refuse to send the main GET request.
When I send a post request through fetch to my node server it successfully serializes the user but req.user comes out as undefined. But it works fine while testing in Postman
I tried including credential:'include' in fetch request. Then an error stating "Failed to load http://localhost:4444/login: 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:3000' is therefore not allowed access." comes out.
I included
app.use(
cors({
credentials: true,
origin: "http://localhost:3000/sign-in"
})
);
But the cross origin request still persists
Here is the code for my fetch req
fetch("http://localhost:4444/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
credentials: "include",
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
})
I am getting the error :
Failed to load http://localhost:3000/users/register: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
On the front end i'm using axios:
const instance = axios.create({
baseURL: 'http://localhost:3000',
timeout: 1000,
headers: {"Access-Control-Allow-Origin": "*"}
});
instance.post('/users/register').then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
and on the server-side using express i am using cors:
var cors = require('cors');
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200
}
app.use(cors(corsOptions));
I am getting a response code of 200 and I do see the 'Access-Control-Allow-Origin' header but i'm not getting anything on the server-side. Any ideas?
You most likely need to also explicitly enable support for OPTIONS requests (i.e. "CORS preflight"). See https://github.com/expressjs/cors#enabling-cors-pre-flight for details on how to do that.
For your specific case, I would add the following:
app.options('/users/register', cors(corsOptions));
Or if you want to enable it for all requests:
app.options('*', cors(corsOptions));
Before asking this, I did have a look at other similar questions, but none of them have been of help as of yet.
I have a react front-end using axios to make api calls to a node backend using express and express session. Once I enter login info on my front end, I send it to my backend where I set a session and return a response to the front end that I set in the localStorage to use for client side validation.
When I try to access a protected api endpoint - from the front end - after logging in, the session does not have any of the information I set in it and thus, gives me an error. However, if I try to login and access the protected endpoint from postman, it works perfectly fine.
Here is my express-session config:
router.use(session({
secret: 'notGoingToWork',
resave: false,
saveUninitialized: true
}))
Here is the api call (after logging in) I am making through axios:
axios.get(`http://localhost:5000/users/personNotes/${JSON.parse(userData).email}`)
.then(response => console.log(response);
I do not know what the issue is and would appreciate any help. Thank you in advance!
try using withCredentials
axios(`http://localhost:5000/users/personNotes/${JSON.parse(userData).email}`, {
method: "get",
withCredentials: true
})
or
axios.defaults.withCredentials = true
You can use axios try withCredentials to true.
For fetch with credentials to include will also work.
fetch(URL,
{
credentials: 'include',
method: 'POST',
body: JSON.stringify(payload),
headers: new Headers({
'Content-Type': 'application/json'
})
})
To use fetch with
credentials: 'include'
I also had to add the following in Express App.js.
To note, 'Access-Control-Allow-Origin' cannot set to '*' with credentials. It must use a specific domain name.
res.setHeader(
'Access-Control-Allow-Origin',
'http://localhost:3000'
);
res.setHeader('Access-Control-Allow-Credentials', 'true');