Reputation: 59
I have a MERN app whose backend is hosted on Heroku and frontend on netlify. I am not able to see the cookies in the browser after deploying the app but it works fine on localhost. I think it is due to different backend and frontend ports, what am I missing, please help
Upvotes: 4
Views: 5139
Reputation: 31
I was facing exactly the same problem. The problem was that cookies are not being set in the browser after successful login/registration. I need that session id set in the cookie to check user authentication on every CRUD/RESTful API call.
As cookies are not set, my API request call does not include it and the user is not authenticated though having logged in successfully. So the user can not access the page that requires session-based authentication. Which of course my entire app relies on.
The thing is that we are using a different domain for both the backend and the front end. By default chrome or other browser does not set cookies for a website(front end) that makes API calls hosted on another domain name for security reason. I do not know how exactly these browsers stop setting cookies but if we do not specify some options they will do for sure.
This works fine when we use http://localhost:3000 for react app and http://localhost:7000 for the backend. But problems come when we deploy on the cloud. There are a couple of things I did that helped me to address this issue. I will illustrate in simple steps specifically on that exact problem part assuming you have done other stuff correctly.
Here are the steps that worked for me. SEE these arrow ⬅️⬅️
marks where I am pointing/ referring to.
TO DO IN FRONTEND REACT APP (step 1 -2)
STEP1: Setup proxy
in package.json
file in react app
. This tells ur React app to include this proxy url before any incomplete URL like "/update/:noteid"
.
If an URL contains something like http
then the proxy will not set the default proxy value.
`"version": "0.1.0",
"private": true,
"proxy": "https://your-backend.com", ⬅️⬅️
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",`
STEP2: Add "credentials" : "include"
API fetch like below
`fetch("your-backend-api-url",{
method: "GET",
credentials: 'include', ⬅️⬅️
headers: { "Content-Type": "application/json" },
... other sptions
});`
TO DO In BACKEND NODE.JS APP
STEP 3: in node.js(or backend app) you need to install cors
in app.js
( or your main file running server)
if you don't know what cors is you may learn from here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
or you can see video see video: https://www.youtube.com/watch?v=CvKPeWojukc&t=410s
To do this
npm i cors
const cors = require("cors");
STEP 4: use cors in app and pass some arguments as shown in example below
along with proxy setting as shown in the code below. And do not forget to add app.set("trust proxy",1);
after adding cors
options
const app = express();
app.use(cors({
origin: "https://yourfrontendurl.com", ⬅️⬅️
credentials: true ⬅️⬅️
}));
app.set("trust proxy",1); ⬅️⬅️
https://yourfrontendurl.com
here in this case) is hosted.
STEP 5: setting up sessions (which I think you have already familiared with) and passing cookie's settings as below
app.use(session({
secret: process.env.sessionSecret, // your secret key to check session
resave: false,
saveUninitialized: false,
cookie: { maxAge: 604800000, //one week(1000*60*60*24*7)
sameSite: "none",
secure : true
},
store: store
}));
And I also suppose that you are doing other stuffs correctly like setting up mongoDB connections etc. This is also my first answer in stack overflow
. Please let me know
if somewhere I am doing wrong
. I will be happy to know that. You can also see my project page that relating this particular problem solution below.
my package.json file --> https://github.com/satyadalei/mynotepedia-frontend/blob/main/package.json
my app.js file --> https://github.com/satyadalei/mynotepedia/blob/main/app.js
Upvotes: 3
Reputation: 2863
You are correct. Cookies are not cross-domain compatible. If it was, it would be a serious security issue. The easiest way to fix your problem would be to send back the cookie as a res
object, and then setting the cookie manually in the frontend.
Take this for example. I'll do this with JavaScript style pseudocode. Don't copy paste this as this most likely wouldn't work right away. This is what you're going to do on the back-end:
// 1. Authenticate the user.
const userData = await authenticateUser();
const userToken = await verifyUser(userData);
// 2. Return the response object.
return response.status(200).json({
status: 'success',
data: userData,
token: userToken,
});
In the front-end:
const response = await axios.post(...); // your API call, will return above object.
// set your authentication token here.
// the 'options' object will contain all possible cookie options, example would be 'secure'.
cookies.set('token', response.data.token, options);
// alternatively, set the cookie in the local storage.
localStorage.setItem('token', response.data.token);
You need to set the cookie accordingly in the front-end.
Further reading: MDN Docs
EDIT: Your question is unclear. First time you talked about cookies, but now you're talking about httpOnly
cookies. Please be more specific in your questions.
It is impossible to set httpOnly
cookies in React.js if it is cross-domain. React is only responsible for the 'view' of the website. httpOnly
cookies are only meant to be set server-side. Client-side JavaScript cannot read or set that specific cookie, but it is able to send it. Unless you have something in your Netlify that can do server-side operations, I don't think that is possible.
Your best bet is to actually just use the same domain.
Upvotes: 7