Why Laravel's reset password feature uses database while email verification uses signed routes?

Viewed 429

Laravel comes with two built-in features called Forgot/Reset Password and Email Verification.
We all know that both are very critical and sensitive operations for an application, so their security must be guaranteed by Laravel framework itself.

However, I got confused why forgot/reset password uses a database table to keep the tokens while email verification uses signed routes feature.

Note: Signed route/URL is a feature provided by Laravel itself. See docs.

Is there any security or performance concerns here? When should we use which one then?

2 Answers

Good point, but then again there is a big difference in their usages.

  • For the email verification you are already signed in and you just need to click the link in the email which will then store the time in the users table email_verified_at column when you performed the action. And this is used to verify that really the owner of the email has registered on your site or that the email is really valid, and not a fake email so someone takes advantage of your site.

  • The forgot password option means that you don't remember your password (and you are logged out), and when you enter your email, the link sent to your email is again a signed route (has the token as the email verification does), but the link also contains the email address, so both the token and the email must match a row in the password_resets table in order to allow the user to change the password.

Having said all of this, I believe it is pretty secure, never had a problem with both. So this is my 2 cents regarding the question, hope it helps. :)

The subject has already been discussed on one of Pull Requests on laravel/framework's repository. You can access it here: [5.7] Database-less Password Reset #23706

To summarize, main concerns were these:

  • URLs can be replayed to reset the token again.
  • Ex-employee could immediately generate password reset links (valid ones) for any account in the system until the encryption keys are rotated. Rotating these keys could be kind of a PITA if you're storing other encrypted data. In a large, high-profile application this becomes a huge source of pain and single point of failure.
  • Links can be essentially "guessed" forever; however, I'm not sure brute-forcing the keys generated by key:generate is realistic.
Related