I make an ecommerce site with nextjs and mongoose using a jwt token in a cookie, going client side in the console, the "application" parameter we can see the cookie which is stored with the name OursiteJWT and it has the value the token :
But after several tests we notice that when I retrieve the token it is undefined pages/orders.js :
import { useEffect, useState } from "react";
import axios from "axios";
import jwt from "jsonwebtoken";
import cookie from "cookie";
function Orders() {
const [orders, setOrders] = useState([]);
useEffect(() => {
async function fetchOrders() {
try {
// Récupère le secret depuis l'API
const secretRes = await axios.get("/api/secret");
const secret = secretRes.data.secret;
console.log(secret);
// Récupère le token JWT depuis les cookies
const cookies = cookie.parse(document.cookie);
const token = cookies.OursiteJWT;
console.log(token);
// Si le token n'est pas présent, redirige vers la page de login
if (!token) {
console.log("pas de token")
return;
}
// Vérifie le token JWT
const decoded = jwt.verify(token, secret);
const userId = decoded._id;
// Récupère les commandes de l'utilisateur depuis l'API
const ordersRes = await axios.get(`/api/orders?user_id=${userId}`);
const orders = ordersRes.data;
setOrders(orders);
} catch (error) {
console.error(error);
}
}
fetchOrders();
}, []);
return (
<div>
{orders.map((order) => (
<div key={order._id}>
<h2>Commande {order._id}</h2>
<p>Utilisateur: {order.name}</p>
<p>Adresse: {order.address}</p>
<p>Ville: {order.city}</p>
<p>Produits:</p>
<ul>
{order.products.map((product) => (
<li key={product._id}>{product.name}</li>
))}
</ul>
</div>
))}
</div>
);
}
export default Orders;
In the console I have "token not found" and the token value is undefined, the secret is correct.
This is how I stored the token :
api/login.js :
import {initMongoose} from "../../lib/mongoose";
import User from '../../models/User';
import { sign } from "jsonwebtoken";
import { serialize } from "cookie";
initMongoose()
const secret = process.env.SECRET;
export default async function handler(req,res){
const {email,password}=req.body;
const user = await User.findOne({email,password});
if(!user){
res.status(401).json({message: "Impossible de trouver un utilisateur"});
return;
}
else{
const token = sign(
{
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30, // 30 days
email: email,
_id: user._id,
},
secret
);
const serialised = serialize("OursiteJWT", token, {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: "strict",
maxAge: 60 * 60 * 24 * 30,
path: "/",
});
res.setHeader("Set-Cookie", serialised);
res.status(200).json({message :"Success!"});
}
}
The reason you are unable to retrieve it is because you are setting httpOnly: true
on the cookie.
Using the HttpOnly flag when generating a cookie helps mitigate the risk of client side script accessing the protected cookie (if the browser supports it).
A cookie with the HttpOnly attribute is inaccessible to the JavaScript
Document.cookie
API; it's only sent to the server. For example, cookies that persist in server-side sessions don't need to be available to JavaScript and should have the HttpOnly attribute. This precaution helps mitigate cross-site scripting (XSS) attacks.
see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies