When trying to refresh the accessToken, the refreshToken is set to undefined. Which is leading to some errors like: jwt malformed (because jwt.verify doesnt work with undefined)
It actually works just fine, if i login first and then try to refresh tokens, but after that the errors are:
jwt malformed – that’s pointing towards the catch block of the controller I have defined for refreshing the tokens.
The problem is that req.cookies.refreshToken is undefined when I tried console logging it. Which means cookies aren’t being sent to the backend.
This is the controller for refreshing the tokens:
const refreshAccessToken = asyncHandler(async (req, res) => {
const incomingRefreshToken = req.cookies.refreshToken || req.body.refreshToken
if (!incomingRefreshToken) {
throw new ApiError(401, "unauthorized request")
}
try {
const decodedToken = await jwt.verify(
incomingRefreshToken,
process.env.REFRESH_TOKEN_SECRET
)
const user = await User.findById(decodedToken?._id)
if (!user) {
throw new ApiError(401, "Invalid refresh token")
}
if (incomingRefreshToken !== user?.refreshToken) {
throw new ApiError(401, "Refresh token is expired or used")
}
const options = {
httpOnly: true,
secure: true
}
const {accessToken, newRefreshToken} = await generateAccessAndRefreshTokens(user._id)
return res
.status(200)
.cookie("accessToken", accessToken, options)
.cookie("refreshToken", newRefreshToken, options)
.json(
new ApiRresponse(
200,
{accessToken, refreshToken: newRefreshToken},
"Access token refreshed"
)
)
} catch (error) {
throw new ApiError(401, error?.message || "Invalid refresh token")
}
})
This is the function thats actually refreshing the tokens:
const generateAccessAndRefreshTokens = async (userId) => {
try {
const user = await User.findById(userId)
const accessToken = await user.generateAccessToken();
const refreshToken = await user.generateRefreshToken();
user.refreshToken = refreshToken;
await user.save( { validateBeforeSave: false } )
return {accessToken, refreshToken}
} catch (error) {
throw new ApiError(500, error.message)
}
}
This is the definition to set or reset the tokens:
userSchema.methods.generateAccessToken = function () {
return jwt.sign(
{
_id: this._id,
email: this.email,
username: this.username,
fullName: this.fullName
},
process.env.ACESS_TOKEN_SECRET,
{
expiresIn: process.env.ACESS_TOKEN_EXPIRY
}
)
}
userSchema.methods.generateRefreshToken = function () {
return jwt.sign(
{
_id: this._id,
},
process.env.REFRESH_TOKEN_SECRET,
{
expiresIn: process.env.REFRESH_TOKEN_EXPIRY
}
)
}
And finally the route:
router.route("/refresh-token").post(refreshAccessToken)
Shreyansh Shukla is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.