Implementing a Reset Password Feature in JavaScript

When building web applications JavaScript, providing a secure and user-friendly way to reset passwords is essential. This feature ensures users can regain access to their accounts without compromising security. Here’s how you can implement a robust reset password feature in JavaScript, integrating both front-end and backend steps.

Key Steps to Implement Password Reset

Front-End: Forgot Password Form

Start with a simple “Forgot Password” form. This form should capture the user’s email address, which is then sent to the backend to initiate the reset process.

code// Front-End (Forgot Password Form)
const forgotPasswordForm = document.getElementById('forgotPasswordForm');

forgotPasswordForm.addEventListener('submit', (event) => {
event.preventDefault();

const email = document.getElementById('email').value;

fetch('/api/forgot-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
})
.then(response => {
if (response.ok) {
alert('A password reset email has been sent to your email address.');
} else {
alert('Error: Unable to send reset email. Please try again later.');
}
});
});

Backend: Generate a Reset Token and Send Email

On the server JavaScript, you need to generate a secure, time-sensitive reset token. This token is then sent to the user’s email along with a password reset link.

  • Token generation: Use libraries like jsonwebtoken (Node.js) or any secure cryptographic library for other languages.
  • Email delivery: Send the email with a trusted service like SendGrid, Mailgun, or AWS SES.
code// Example in Node.js (using jsonwebtoken and nodemailer)
const jwt = require('jsonwebtoken');
const nodemailer = require('nodemailer');

app.post('/api/forgot-password', async (req, res) => {
const { email } = req.body;
const user = await User.findOne({ email }); // Find user by email

if (!user) {
return res.status(404).send('User not found.');
}

const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });

const resetLink = `${process.env.FRONTEND_URL}/reset-password?token=${token}`;

// Send email
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS
}
});

await transporter.sendMail({
from: '"Your App" <support@yourapp.com>',
to: user.email,
subject: 'Password Reset',
html: `<p>Click <a href="${resetLink}">here</a> to reset your password.</p>`
});

res.send('Password reset email sent.');
});

Front-End: Reset Password Form

When users click the reset link, direct them to a “Reset Password” page where they can enter a new password. Validate the reset token in the backend before allowing them to set a new password.

code// Front-End (Reset Password Form)
const resetPasswordForm = document.getElementById('resetPasswordForm');

resetPasswordForm.addEventListener('submit', (event) => {
event.preventDefault();

const token = document.getElementById('token').value;
const newPassword = document.getElementById('newPassword').value;

fetch('/api/reset-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ token, newPassword })
})
.then(response => {
if (response.ok) {
alert('Password has been successfully updated.');
} else {
alert('Error: Unable to reset password. Please try again.');
}
});
});

Backend: Validate Token and Update Password

Validate the reset token and update the user’s password securely in the backend.

code// Backend (Node.js Example)
app.post('/api/reset-password', async (req, res) => {
const { token, newPassword } = req.body;

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.userId);

if (!user) {
return res.status(404).send('User not found.');
}

// Update password securely
user.password = await bcrypt.hash(newPassword, 10);
await user.save();

res.send('Password updated successfully.');
} catch (error) {
res.status(400).send('Invalid or expired token.');
}
});

Important Considerations

  1. Security:
    • Use cryptographically secure methods to generate tokens.
    • Ensure tokens have a short expiration time (e.g., 1 hour).
    • Securely hash passwords using libraries like bcrypt.
  2. Error Handling:
    • Gracefully handle cases where the email is invalid or the token is expired.
    • Log errors without exposing sensitive information to the user.
  3. User Experience:
    • Provide clear feedback and instructions at every step.
    • Consider showing a success message even if the email address is invalid to avoid exposing user data.
  4. Backend Practices:
    • Always validate inputs to prevent injection attacks.
    • Use HTTPS to secure data transmission.

By following these steps, you can build a secure and user-friendly password reset feature for your application. Tailor the implementation to fit your technology stack and ensure compliance with security best practices.

Related blog posts