Hacker News new | ask | show | jobs
by bgentry 4905 days ago
The ActiveRecord query that caused this was along the lines of:

    User.find_by_email_and_token(params[:email], params[:token])
If the token is nil, it basically turns into a `find_by_email`.

I'll also add that while we had tests that were intended to avoid this bad behavior, these tests were unfortunately broken and were instead verifying the incorrect behavior.

1 comments

It's interesting how differently Django handles password resets - no nonce is generated.

Instead, the user is emailed a token that's just her user ID, HMAC-signed with the last login date and a secret site key.

You can't generate valid reset links without knowing the secret key and you can't tamper with the one you got because it's HMAC-signed. By adding the last login date to the HMAC you make sure the link can be used only once. After a user resets her password, the last login date is updated to now so the link is no longer valid due to broken HMAC.

I like this solution because it doesn't rely on storing any state anywhere between requesting the reset and completing it.

This is pretty much exactly what Drupal does as well, with the exception of using the user's password hash instead of the ID as input before hashing and it also stores the timestamp of the reset request as part of the URL (and the token) to allow for expiring password resets.