R
Railway•17mo ago
ntraithi(Min)

Set-Cookie isn't sent with res header on production

Hi everyone, thanks for reading this i'm a self taught developer and I've already spent 5 days straight to make it work alone but really couldn't 😢 I use Passport.js for session-based authentication which requires cookies to work. My server and client are on different domain (client : https://min-workout-timer.onrender.com/ server: https://workout-timer-server-production.up.railway.app/) When I tested it locally, both works fine. 1.Passport.js serialize and deserialize properly 2. Server res header has 'Set-Cookie' on the initial login and Client has 'cookie' in the subsequent request. However when I built and deployed both of them, 1. Passport.js only serialize but doesn't deserialize 2. There's no cookie at all in the req and res from both sides. Here are some configuration from my server and client side index.ts (server side)
app.use(
cors({
origin: 'https://min-workout-timer.onrender.com/' || 'http://127.0.0.1:5173',
credentials: true,
})
);

const storeOptions = {
.....
};

const sessionStore = new MySQLStore(storeOptions);

app.use(
session({
secret: process.env.MY_SESSION_SECRET,
store: sessionStore,
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
sameSite: 'none',
httpOnly: true,
},
})
);
app.use(
cors({
origin: 'https://min-workout-timer.onrender.com/' || 'http://127.0.0.1:5173',
credentials: true,
})
);

const storeOptions = {
.....
};

const sessionStore = new MySQLStore(storeOptions);

app.use(
session({
secret: process.env.MY_SESSION_SECRET,
store: sessionStore,
resave: false,
saveUninitialized: false,
cookie: {
secure: true,
sameSite: 'none',
httpOnly: true,
},
})
);
signin.ts (client side)
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
try {
const res = await axios.post<FormData>(
'https://localhost:8080/api/users/signin',
{
email: formData?.email,
password: formData?.password,
},
{ withCredentials: true }
);
if (res.status === 200) {
localStorage.setItem('user', JSON.stringify(res.data));
navigate('/plan');
}
} catch (error: any) {
if (error.response.status === 403) alert(error.response.data);
else alert('Server failed to respond');
}
}
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
try {
const res = await axios.post<FormData>(
'https://localhost:8080/api/users/signin',
{
email: formData?.email,
password: formData?.password,
},
{ withCredentials: true }
);
if (res.status === 200) {
localStorage.setItem('user', JSON.stringify(res.data));
navigate('/plan');
}
} catch (error: any) {
if (error.response.status === 403) alert(error.response.data);
else alert('Server failed to respond');
}
}
At this point idek if cross site cookie still work😖
Solution:
Gonna close this with the solution 1. check cors config ``` app.use(...
Jump to solution
12 Replies
Percy
Percy•17mo ago
Project ID: N/A
ntraithi(Min)
ntraithi(Min)OP•17mo ago
N/A Project ID:4e42c618-d84d-4687-9344-b9aa95f39c6c
Brody
Brody•17mo ago
my initial guess is that your server doesn't know it's running behind a proxy and is refusing to set cookies on an http request you may need to setup your app to trust the X-* headers that railways proxy sets
ntraithi(Min)
ntraithi(Min)OP•17mo ago
Hi Brody thanks for checking in. Could you provide more detail about how this work? do i just set app.enable('trust proxy',true or client ip.address)? or is there any other thing I should be checking on?
Brody
Brody•17mo ago
im sorry i wouldn't know how to answer that without first having to google for the answer as im not a JavaScript developer, i recommend you look into what is required to set cookies behind a proxy
ntraithi(Min)
ntraithi(Min)OP•17mo ago
thank you so much for your advice. I learned from an online course and they dont really teach you how these infrastructure stuff works. Please correct me if Im wrong. 1.When we use CORS, we’re telling server to handle request and response from specific origin only 2. When we deploy to Railway, our server is running behind a proxy server which is like a middleman now. 3. The server doesn’t know that there’s a proxy, and knows only the origin stated in CORS so it refuses to send set cookie to proxy and also to the client. If we modify the server code to let them know that there’s a proxy (by setting server to trust proxy) , then it should be able to send cookie through proxy and to client. So does the client has to send their request to proxy address now instead of https://workout-timer-server-production.up.railway.app/ ??
Brody
Brody•17mo ago
1. cors headers are rules for the browser to enforce, not the server 2. railways proxy comes first 3. by default your code wouldn't know its running behind a proxy 4? no, you dont have to change the request url, the railway provided domain is the proxy address
ntraithi(Min)
ntraithi(Min)OP•17mo ago
Hey @Brody , just wanna let you know it's working now. Thank you so much. As a self-taught dev, it means the world to me and I truly appreciate your help. God bless you man 🙌
Brody
Brody•17mo ago
ah that's awesome, I'm glad I could at least provide some assistance
Solution
ntraithi(Min)
ntraithi(Min)•17mo ago
Gonna close this with the solution 1. check cors config
app.use(
cors({
origin: 'your url link';
credentials: true,
})
);
app.use(
cors({
origin: 'your url link';
credentials: true,
})
);
2.check your session, cookie to have these 3 set.
app.use(
session({
...
cookie: {
secure: true,
sameSite: 'none',
httpOnly: true,
},
})
);
app.use(
session({
...
cookie: {
secure: true,
sameSite: 'none',
httpOnly: true,
},
})
);
I also set domain to client url at first, didn't think it's would cause problem. Unfortunately when I removed it, it worked. 3. trust proxy app.set('trust proxy', 1); 4. On your client side, when sending request include your credentials
const res = await axios.post<FormData>(
'https://your-server-production.up.railway.app/api/users/signin',
{
email: formData?.email,
password: formData?.password,
},
{ withCredentials: true }
);
const res = await axios.post<FormData>(
'https://your-server-production.up.railway.app/api/users/signin',
{
email: formData?.email,
password: formData?.password,
},
{ withCredentials: true }
);
5. If you use see set-cookie in the response header, but no cookies in the next request header. Check your Browser cookie setting and allow 3rd party cookie.
Brody
Brody•17mo ago
that's awesome, that will be a big help to anyone in the future, but I see you tried to do bold text formatting in the code blocks, unfortunately that doesn't work, if you wouldn't mind removing that as it could cause some confusion at first thanks again! 🙂
ntraithi(Min)
ntraithi(Min)OP•17mo ago
done! thanks again man
Want results from more Discord servers?
Add your server