In multiple systems I've built/supported I've seen user management do the following for password reset: generated a password reset token via some hashing method and email the link with token to user. Usually there are bits of information included into these tokens - user id, user security stamp, date, server name or machine key (I'm going with ASP.Net Identity framework now). When user follows the link with token, framework follows the same process to rebuild the token and compares the token with user-provided one. If tokens match - allow for password reset.
A lot of time machine-related parts of token change from the moment of token generation to the moment when user uses that token. I.e. IIS restarts and this can invalidate token in some cases. When web-application is spread on multiple servers (i.e. web-farm), chances of this token to be invalid are higher (i.e. machine keys are not synchronised between machines, etc.).
Now I'm considering a scenario where I store the generated token in the database, add a generation timestamp. And when user comes back with the token, I don't re-generate the token, but rather compare the stored token, validate the timestamp and allow/disallow password reset.
Given that token now becomes a password (though time limited), for a good measure I can treat it as password and store hash only.
I can't think of flaws in this scenario, but I'm sure there some. Given the implementation of this scenario is solid, what other issues might arise from storing the tokens?
server name or machine key
... uh, do they even have any guarantee that they'll hit the same server/machine anyways? If you're running a load-balanced app (or something with ephemeral instances, like in a docker container), you're pretty much guaranteed to hit a different process. All the information used should be configurable, and setup the same on each instance.