I recently deployed my first full stack app on render:
I can successfully register and log in, but any requests made while being logged in get stuck pending and won’t resolve.
I assume it has something to do with cookies not being able to travel between front- and backend, but they are set correctly when checking chrome dev tools.
FRONTEND: https://example.com
NEXT_PUBLIC_BACKEND: https://api.example.com
cookiesOptions:
const cookiesOptions: CookieOptions = {
sameSite: "none",
secure: true,
domain: ".example.com",
httpOnly: true,
};
CORS:
app.use(
cors({
origin: process.env.FRONTEND,
credentials: true,
})
);
loginUserHandler (backend):
export const loginUserHandler = async (
req: Request<{}, {}, LoginUserInput>,
res: Response,
next: NextFunction
) => {
try {
const { email, password } = req.body;
const user = await findUserByEmail({ email });
// 1. Check if user exist
if (!user) {
return next(new AppError(401, "Invalid email or password"));
}
// 2. Check if password is valid
if (!(await User.comparePasswords(password, user.password))) {
return next(new AppError(401, "Invalid email or password"));
}
// 3. Sign Access and Refresh Tokens
const { access_token, refresh_token } = await signTokens(user);
// 4. Add Cookies
res.cookie("access_token", access_token, accessTokenCookieOptions);
res.cookie("refresh_token", refresh_token, refreshTokenCookieOptions);
res.cookie("logged_in", true, {
...accessTokenCookieOptions,
httpOnly: false,
});
// 5. Send response
res.status(200).json({
status: "success",
access_token,
});
} catch (err: any) {
next(err);
}
};
login (frontend):
export async function login(email: string, password: string) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND}/api/auth/login`,
{
method: "POST",
headers: { "Content-type": "application/json" },
credentials: "include",
body: JSON.stringify({
email,
password,
}),
}
);
return response;
}
Until here, everything works fine. I am able to log in and the cookies are set.
The following does not work after being logged in.
getMeHandler (backend):
export const getMeHandler = async (
req: Request,
res: Response,
next: NextFunction
) => {
try {
const user = res.locals.user;
if (!user) {
return next(new AppError(404, "User not found"));
}
res.status(200).status(200).json({
status: "success",
data: {
user,
},
});
} catch (err: any) {
next(err);
}
};
getUser (frontend):
export async function getUser() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND}/api/users/me`,
{
method: "GET",
credentials: "include",
}
);
const responseData: IresponseData = await response.json();
if (responseData.status === "error") {
throw new UserError("Oh no, could not get the requested user information!");
} else if (responseData.data) {
return responseData.data.user;
}
}