Can you guys check my code, i have a Nextjs and Node api app, and i'm currently having a problem on getting the cookie from my api to my Next app, the signInUser api i made should return a generated jwt cookie but when i use it in my Next app it doesnt show in my devtools application-cookies, however when trying the api from postman or thunder client i see the jwt token in the cookies tab, what am I missing?
here is my backend Node api code for signin
const app = express();
app.use(cors());
export const signInUser = async (
req: express.Request,
res: express.Response
) => {
const { username, password } = req.body;
try {
let user = await getUserByEmail(username).select(
"+authentication.password"
);
if (!user) {
user = await getUserByUserName(username).select(
"+authentication.password"
);
}
if (!user) {
const response: ResponseProps = {
isError: true,
message: "Invalid username or email",
};
res.status(400).json(response);
return;
}
const passwordMatch = await bcrypt.compare(
password,
user.authentication.password
);
if (!passwordMatch) {
const response: ResponseProps = {
isError: true,
message: "Invalid username/email or password",
};
res.status(400).json(response);
return;
}
const response: ResponseProps = {
isError: false,
message: "Sign in successful",
data: user,
};
this is my custom generateToken method that takes the express.Response and user.Id from signin api
generateToken(res, user.id);
res.status(200).json(response);
} catch (error) {
res.status(400).json(error);
}
};
export const generateToken = (res: express.Response, userId: String) => {
const token = jwt.sign({ userId }, process.env.JWT_SECRET, {
expiresIn: "1d",
});
res.cookie("jwt", token, {
httpOnly: true,
secure: process.env.SERVER_ENVIRONMENT !== "development",
sameSite: "strict",
maxAge: 86400,
});
};
here is my frontend Next code for signin
const handleSignIn = async (values: z.infer<typeof formSchema>) => {
setIsLoading(true);
try {
const res = await axios.post(SIGNIN_URL, values);
const data = res.data;
if (data.isError === true) {
setSignInError("Invalid username or password.");
} else {
router.push("/home");
form.reset();
setSignInError("");
toast({
duration: 5000,
variant: "default",
title: "Success!",
description: "Welcome back! What's up?",
});
}
setIsLoading(false);
} catch (error) {
toast({
duration: 5000,
variant: "destructive",
title: "Uh oh! Something went wrong.",
description: "There was a problem with your request.",
});
setIsLoading(false);
}
};
the only thing I can think of is res.cookie
might not set cookies for different domains. Postman does not enforce the same-origin policy or have the same security restrictions as browsers. cors
is implemented by browser, which is why I guess it works in postman. if you set the cors in express with options
import cors from "cors";
const options: cors.CorsOptions = {
allowedHeaders: [
"Origin",
"X-Requested-With",
"Content-Type",
"Accept",
"X-Access-Token",
],
credentials: true,
methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
// whatever port for next.js
origin: "http://localhost:3000",
preflightContinue: true,
};
const app = express();
app.use(cors(options));