What a relief to see such an earnest writeup. A pity, it’s a rare sight in this sub, I’d say there are ten half-assed illiterate guides to one good article. As a community, we need more of this kind.
Thanks for the feedback! I have another one about static code analysis tools coming. Keep an eye out for it!
Half ass tutorials & write ups are pretty popular everywhere else, sadly.. arduino tutorials are probably the worst, many don’t even compile but when they do there’s always random unused variables all over, etc. I get a lot of people are learning but you shouldn’t write up tutorials if you are brand new..
Should more correctly be described as a password reset, not password recovery.
So a correct way to recover a password is called a password reset 🙂
What? That’s an odd name.


I’ve have called them: “password chazwazzers”.
Good article, some nice reminders that hopefully most experienced PHP devs know, but may have forgotten. In my case, it was a good reminder that time-based tokens aren’t a good idea, even when encrypted… this will be rectified shortly
Glad it was helpful!
Great article! For clarity’s sake though, please consider adding the word “don’t” in front of every item in your “Don’t” list at the end of the article for two reasons:
Provides more clarity to a tired brain
A google search results page could return just a portion of your page and it reads like a “Do” list. I.e., “6) Use encryption”
Good advice and solid explanation!
To further harden this, there is a nice method of using split tokens to mitigate timing attacks as written by Paragon Initiative.
I’m a big fan of the work Scott has been doing in the community around security. Part of the motivation for writing it was seeing all the cool things that he’s been writing, but them not surfacing in a way that newcomers to the language might find / could easily digest.
This is a hardened approach I’ve used in the past:
Build a JWT / PASETO, with the jti claim set to a UUID, sub set to the username and exp set to +x hours
Sign with some secret (using HMAC for JWT, local purpose for PASETO)
Insert token details into a table, but don’t insert the actual token value itself – just the ID, username, issued at & expires at
Email the token to user
When a token is received by your API, first verify it is valid, signed by your secret and not expired
Next extract the jti claim and query your database – ensure the token claims matches the state in your table & the token isn’t marked as revoked
Assuming all is good, update the users password and mark the token as revoked
This way, leaking of the database state alone does not enable access. Nor does leaking of the secret. Both have to be compromised to gain access to someones account.
Excellent starting place – a few extras that might be worth consideration for opening developers’ eyes to the kind of low-down tactics their recovery processes will face:


Don’t disclose whether or not a particular email address is valid if there is no other way for an attacker to confirm validity. Display the same “If this address was registered, you will receive an email” message for a successful or failed lookup. This prevents account enumeration which may be used for a bruteforce attack, spear-phishing, etc.
Do rate-limit – or at the very least least log – password recovery attempts. Available information (IP address, ASN, browser agent – anything that makes it easier to identify a scripted attack) can then be used to identify and handle repeat offenders or inject a CAPTCHA if your system is resource-constrained. If your system is actively ignoring a user who has submitted 1000 password recovery attempts in the last hour, it’s better to just keep displaying the same message and let them feed your system more information on which accounts they’re targeting and what information they have (though less of an issue with password recovery, this strategy works beautifully for payment information fraudsters – e.g. it’s pretty damn rare to see a valid CC purchase originating from a datacenter’s ASN – and knowing that XYZ email addresses/CC#’s and other items of information are being used by an obvious fraudster makes it trivially easy to shut them down as they try different tactics).
Solid article with great advice!
While I believe it is implied in step 5, step 3 could use a clear note to tie the token to the account for which it was requested.
Members
Online

source