I am first time making APIs about forgot password and then reset password. I am facing strange issue. There is not a single error, it gives me success status that password is updated. The problem is that in my database password is NOT updated.
User schema:
const UserSchema = new mongoose.Schema({
email: { type: String, required: true, min: 6, max: 255 },
password: { type: String, required: true, min: 4, max: 1024 },
resetLink: { data: String, default: "" },
});
module.exports = mongoose.model("Users", UserSchema);
Forgot password: (when user click forgot password and writes an email, this happens:
router.post("/forgot-password", async (req, res) => {
try {
const { email } = req.body.email;
//check if user is alredy in database
const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("User doesn't exist");
// create token
const token = jwt.sign({ email: user.email, _id: user._id }, secretKey, {
expiresIn: "15m",
});
// generate resetUrl link using the token and id
const link = `http://localhost:3000/api/users/reset-password/${user._id}/${token}`;
res.send("password reset link has been sent to an email");
// SEND EMAIL
let transporter = nodemailer.createTransport({
host: "*******",
port: 587,
secure: false,
auth: {
user: "*******",
pass: "*******",
},
});
let info = transporter.sendMail({
from: '"Reset password" <*********>', // sender address
to: req.body.email, // list of receivers
subject: "Hello", // Subject line
html: `<p>Visit the: ${link}</p>`,
});
user.updateOne({ resetLink: token });
} catch (err) {
res.status(400).json(err);
}
});
Change password process Firstly get method
router.get("/reset-password/:id/:token", async (req: any, res: any) => {
const { id, token } = req.params;
// Check if ID is valid
const user = await User.findOne({ _id: id });
if (!user)
return res.status(400).send("User doesn't exist");
try {
const verify = jwt.verify(token, secretKey);
res.render("reset-password", { email: user.email });
} catch (err) {
res.status(400).json(err);
}
});
And then post method
router.post("/reset-password/:id/:token", async (req: any, res: any) => {
const { id, token } = req.params;
const { password } = req.body.password;
const { password2 } = req.body.password2;
// Validate if user is alredy in database
const user = await User.findOne({ _id: id });
if (!user) return res.status(400).send("User doesn't exist");
try {
const verify = jwt.verify(token, secretKey);
// validate if password 1 and password 2 MATCH -> NOT YET
// Update password
const password = req.body.password2;
bcrypt.genSalt(saltRounds, (err: any, salt: any) => {
if (err) return res.json(err);
bcrypt.hash(password, salt, async (err: any, hash: any) => {
await user.save({ password: hash });
res.send("Password is updated!");
});
});
} catch (err) {
res.status(400).json(err);
}
});
And I would alse be very happy, if someone could tell me or give me an advice, if there should me some changed regards to better security.
Update: I will be using then Angular for frontend, so I am not even sure, if the get method in change password is needed (where i just make res.render("reset-password", { email: user.email }); ) An explanation of this line would be perfect
Thanks to everyone!
CodePudding user response:
Try to pass password2
to the hash
function instead of generating a new variable and change the way you set the new password.
Plus, you should await
the save()
function:
router.post("/reset-password/:id/:token", async (req: any, res: any) => {
const { id, token } = req.params;
const { password, password2 } = req.body;
// Validate if user is alredy in database
const user = await User.findOne({ _id: id });
if (!user) return res.status(400).send("User doesn't exist");
try {
const verify = jwt.verify(token, secretKey);
// validate if password 1 and password 2 MATCH -> NOT YET
// Update password
bcrypt.genSalt(saltRounds, (err: any, salt: any) => {
if (err) return res.json(err);
bcrypt.hash(password2, salt, async (err: any, hash: any) => {
user.password = hash
await user.save()
res.send("Password is updated!");
});
});
} catch (err) {
res.status(400).json(err);
}
});