Cookie isn't being saved on custom auth routes

I'm using express with better auth. I know that better auth can create the endpoints by itself through the toNodeHandler. But I don't want to use that. I just want to create all the auth routes manually like this:
app.post("/api/auth/signin", async (req, res) => {
try {
const { email, password } = req.body;
const session = await auth.api.signInEmail({
body: { email, password },
headers: fromNodeHeaders(req.headers),
returnHeaders: true,
});

console.log("User signed in:", session);
res.status(200).json(session);
} catch (error: any) {
res.status(401).json({ error: error.message });
}
});
app.post("/api/auth/signin", async (req, res) => {
try {
const { email, password } = req.body;
const session = await auth.api.signInEmail({
body: { email, password },
headers: fromNodeHeaders(req.headers),
returnHeaders: true,
});

console.log("User signed in:", session);
res.status(200).json(session);
} catch (error: any) {
res.status(401).json({ error: error.message });
}
});
The issue is that it doesn't save the cookie. The cookie is indeed generated via better auth. But it's never saved. So, it always returns null with getSession. How do I solve this issue?
Solution:
Here, you’re passing returnHeader: true, which ensures that the signInEmail function returns the response headers within the data. From there, you can extract the cookies using let cookies = session.headers.getSetCookie(), which provides the cookies that need to be set. Finally, you manually set these cookies using your controller’s response object like this: res.setHeader('Set-Cookie', cookies).
Jump to solution
3 Replies
Solution
Vishnu
Vishnu16h ago
Here, you’re passing returnHeader: true, which ensures that the signInEmail function returns the response headers within the data. From there, you can extract the cookies using let cookies = session.headers.getSetCookie(), which provides the cookies that need to be set. Finally, you manually set these cookies using your controller’s response object like this: res.setHeader('Set-Cookie', cookies).
Vishnu
Vishnu16h ago
We use the Set-Cookie header to send cookies from the server to the client’s browser. Unlike regular HTTP headers (where multiple values can safely be combined into a single header using commas), cookies are more complex, their values may themselves contain commas, semicolons, or other special characters. If we were to combine multiple cookies into one comma-separated header, it would be extremely difficult (and unreliable) to parse them correctly. That’s why the HTTP specification allows multiple Set-Cookie headers, one for each cookie. Each Set-Cookie header acts like an instruction to the browser, telling it what cookie to store, with which attributes (like HttpOnly, Secure, or SameSite). The browser then automatically stores and sends these cookies in subsequent requests. the cookies variable contains an array of cookie strings returned from session.headers.getSetCookie(). The framework (like Express or Node’s native res object) knows how to handle this array it automatically sends multiple Set-Cookie headers, one per cookie, rather than joining them with commas.
doomer
doomerOP8h ago
@Vishnu thank you. it worked

Did you find this page helpful?