patterncsharpMinor
"Forgot password" functionality
Viewed 0 times
forgotfunctionalitypassword
Problem
I want to implement the "forgot password" functionality in Asp.Net MVC 5. Here is the code flow:
Please tell me where I can improve.
```
public ActionResult ForgotPassword()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ForgotPassword(ForgotPasswordMV viewModel)
{
if (ModelState.IsValid)
{
if (SecurityHelper.SendEmail(viewModel.Email))
return RedirectToAction("VerifyToken", new { email = viewModel.Email });
ModelState.AddModelError("Email", "Email not found");
}
return View();
}
public ActionResult VerifyToken(string email = null)
{
VerifyTokenMV viewModel = new VerifyTokenMV
{
Email = email,
Token = ""
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult VerifyToken(VerifyTokenMV viewModel)
{
if (ModelState.IsValid)
{
if (SecurityHelper.VerifyToken(viewModel.Token, viewModel.Email))
return RedirectToAction("ConfirmPassword", new { email = viewModel.Email });
ModelState.AddModelError("Token", "Token does not match");
}
return View();
}
public ActionResult ConfirmPassword(string email = null)
{
ConfirmPasswordMV viewModel = new ConfirmPasswordMV
{
EmailID = email
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ConfirmPassword(ConfirmPasswordMV viewModel)
{
if (ModelState.IsValid)
{
if (viewModel.Password == viewModel.ConfirmPassword)
{
SecurityHelper.UpdatePassword(viewModel.EmailID, viewModel.Password);
TempData["Message"] = "Your password has been updated.";
return RedirectToAction(action, homeController);
}
ModelState.AddModelError("", "Password does not match.");
- Take user email ID
- Let the user enter the token received in his email inbox
- If the token matches then redirect for password reset page
- Set the new password
Please tell me where I can improve.
```
public ActionResult ForgotPassword()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ForgotPassword(ForgotPasswordMV viewModel)
{
if (ModelState.IsValid)
{
if (SecurityHelper.SendEmail(viewModel.Email))
return RedirectToAction("VerifyToken", new { email = viewModel.Email });
ModelState.AddModelError("Email", "Email not found");
}
return View();
}
public ActionResult VerifyToken(string email = null)
{
VerifyTokenMV viewModel = new VerifyTokenMV
{
Email = email,
Token = ""
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult VerifyToken(VerifyTokenMV viewModel)
{
if (ModelState.IsValid)
{
if (SecurityHelper.VerifyToken(viewModel.Token, viewModel.Email))
return RedirectToAction("ConfirmPassword", new { email = viewModel.Email });
ModelState.AddModelError("Token", "Token does not match");
}
return View();
}
public ActionResult ConfirmPassword(string email = null)
{
ConfirmPasswordMV viewModel = new ConfirmPasswordMV
{
EmailID = email
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ConfirmPassword(ConfirmPasswordMV viewModel)
{
if (ModelState.IsValid)
{
if (viewModel.Password == viewModel.ConfirmPassword)
{
SecurityHelper.UpdatePassword(viewModel.EmailID, viewModel.Password);
TempData["Message"] = "Your password has been updated.";
return RedirectToAction(action, homeController);
}
ModelState.AddModelError("", "Password does not match.");
Solution
Is this secure?
No. It isn't secure because you can change anyone's email address on the last step. To do so, all I need to do is change the
In the final step you must verify the token. You don't need step 2 at all.
There are two requests you need once you have your reset token. Typically you'd click a link in the email.
GET passwordReset (pass in the reset token)
POST passwordReset (pass in the reset token and the new password)
Use the reset token to look up the email that you're changing the password for. The token should be time limited, long and random to avoid guessing.
No. It isn't secure because you can change anyone's email address on the last step. To do so, all I need to do is change the
emailId stored in the hidden field (for example, using my browser tools).In the final step you must verify the token. You don't need step 2 at all.
There are two requests you need once you have your reset token. Typically you'd click a link in the email.
GET passwordReset (pass in the reset token)
POST passwordReset (pass in the reset token and the new password)
Use the reset token to look up the email that you're changing the password for. The token should be time limited, long and random to avoid guessing.
Context
StackExchange Code Review Q#161566, answer score: 3
Revisions (0)
No revisions yet.