We change password by using the registered email. when we dont know password.
Let's take a look at how this process works.
//api/routes/auth.js
router.post('/forgotpasswrod', forgotPassword); [ 1 ]
router.put('/resetpassword/:resettoken', resetPassword); [ 2 ]
[ 1 ] forgotPassword() method
When we got request POST 'api/v1/forgotpassword', call forgotPassword() method
forgotPassword() method do these.
- Got 'email' from client input 'request.body.email'.
- Find email equals to 'request.body.email', if cant occur Error.
const user = await User.findOne({ email: req.body.email });
if (!user) {
return next(new ErrorResponse('There is no user with that email', 404));
}
- Issue resetToken (we already defined getResetPasswordToken() method in User model.) shoud check only send resetToken(it isn't hashed) not ResetPasswordToken(it is hashed).
// Get reset token using 'bcryto'
const resetToken = user.getResetPasswordToken();
!! Should check getResetPasswordToken() method return resettoken(not hashed)
!! But save resetPasswordToken(hashed) to this.model document.
- Send email with resetUrl which have resetToken.
const resetUrl = `${req.protocol}://${req.get('host')}/api/v1/auth/resetpassword/${resetToken}`;
const message = `Plase make a PUT request to: ${resetUrl}`;
try {
await sendEmail({
email: user.email,
subject: 'Password reset token',
message
});
res.status(200).json({ success: true, data: 'Email sent'});
} catch (err) {
console.log(err);
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefiend;
return next(new ErrorResponse('Email could not be sent', 500));
}
Full forgotPassword() method
exports.forgotPassword = asyncHandler(async (req, res, next) => {
// get email which is equal to req.body.email/user input
const user = await User.findOne({ email: req.body.email });
// Error cant find equal eamil
if (!user) {
return next(new ErrorResponse('There is no user with that email', 404));
}
// Get reset token using "bcryto" (make random number and hash that number)
const resetToken = user.getResetPasswordToken();
await user.save({ validateBeforeSave: false });
// Create reset url
const resetUrl = `${req.protocol}://${req.get(
'host'
)}/api/v1/auth/resetpassword/${resetToken}`;
const message = `You are receiving this email because you (or someone else) has requested the reset of a password. Please make a PUT request to: \n\n ${resetUrl}`;
// Send email with resetUrl message in that message there's link you can change password.
try {
await sendEmail({
email: user.email,
subject: 'Password reset token',
message
});
res.status(200).json({ success: true, data: 'Email sent' });
} catch (err) {
console.log(err);
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefined;
await user.save({ validateBeforeSave: false });
return next(new ErrorResponse('Email could not be sent', 500));
}
});
[ 2 ] resetPassword() method
- Only from reigstered email, user can accesses resetPassword form.
- Input newPassword and submit
- Hash 'resettoken' and then finds user document matching resetPasswordToken. and also resetPasswordExpire is greater than Date.now(). [ Validation ]
const resetPasswordToken = crypto
.createHash('sha256')
.update(req.params.resettoken)
.digest('hex');
const user = await User.findOne({
resetPasswordToken,
resetPasswordExpire: { $gt: Date.now() }
});
if (!user) {
return next(new ErrorResponse('Invalid token', 400));
}
- If valid, update user data. and delete token(by referencing 'undefined')
// Set new password
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefined;
await user.save();
- sendTokenResponse
sendTokenResponse(user, 200, res);
Full resetPassword() method
exports.resetPassword = asyncHandler(async (req, res, next) => {
// Get hashed token
// Check User.getResetToken() just pass resettoken but save hashed token to this.model
// only registered email can get resetUrl so can get reset token.
const resetPasswordToken = crypto
.createHash('sha256')
.update(req.params.resettoken)
.digest('hex');
const user = await User.findOne({
resetPasswordToken,
resetPasswordExpire: { $gt: Date.now() } // Should be greater than Date.now, it
});
if (!user) {
return next(new ErrorResponse('Invalid token', 400));
}
// Set new password
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefined;
await user.save();
sendTokenResponse(user, 200, res);
});
'express' 카테고리의 다른 글
How to show joined models [mongoose] (0) | 2020.05.21 |
---|---|
Permission check on user's actions [Express, Node] (0) | 2020.05.21 |
Query mongoose (0) | 2020.05.21 |
So what do I do with Token? (0) | 2020.05.19 |
TOKEN authentication (0) | 2020.05.19 |