router and controller code is given below: tried using jwt decoder, it provides object : {_id, iat, exp} but in postman it return the empty object
===router===
router.get("/secret", requireSignin, (req, res) => {
res.json({
user: req.user,
});
});
===controller===
exports.requireSignin = expressJwt({
secret: process.env.JWT_SECRET,
algorithms: ["HS256"],
userProperty: "auth",
});```
For me, this happened when I did not async-await a function that was going to return a signed token that I wrote against a MongoDB schema like this
const sendCustomerToken = (customer, statusCode, res) => { const token = customer.getSignedToken(); res.status(statusCode).json({ success: true, token }); };
Basically, it's returning a promise, if you don't await it, it will return a null or empty object because it is procedural

however if you await it, it waits for the time the string is available then return it like this
const sendCustomerToken = async (customer, statusCode, res) => { const token = await customer.getSignedToken(); res.status(statusCode).json({ success: true, token }); };
schema method
customerAuthSchema.methods.getSignedToken = async function() { return jwt.sign({ id: this._id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRE, }); };
you may want to check promises in your code where you may be querying the DB.
also if decode is not working, try using jwt sign method which recieves a payload, secret and option - payload is the protected data you want to return, secret is your normal string you can generate using crypto and option is simply the life time of your token. like so
function() {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRE, });};`
with env variables like this
PORT=5000 JWT_SECRET=4de5b205fa171927adb1444c06bd990fadd45ffe7a1309def8b5a JWT_EXPIRE=10min