I have a Node.js/Express 4/JWT user authentication service using Passport.js, with Sequelize and MySQL for database.
In my service, upon signing up/resetting a password, the user will be redirected to a page telling them to
- click the link in the email that was just sent, or
- click a button to resend the email (if they did not get it)
In the database I have a dynamic_urls
table for activate/reset links. The dynamic_urls
table has a cap of 5 resend attempts before they are directed to contact the admin (obv. incremented with every resend). The URL itself is generated via JWT, with a payload of the user's id, password hashed password, with their account creation date, and a private key of a long "secret" string. It is then stored in the database until it is clicked or expires.
I have a few questions for best info sec practices with JWT, namely:
- Should I even care about having the resend button have a random URL?
I assume that I must, because the resend request has to correspond to the correct dynamic URL, which requires user information, which must not be leaked.
And if so:
- What should I use for in the payload when creating the dynamic URL of the resend button?
I assume I shouldn't use the same/similar payload that I used to make the email link. UUID maybe? (but then I'd have to presumably stash the UUID in the database as well, no?) - Should I renew the resend URL with each resend attempt.
(E.g. each resend lands user on new page with new unique resend link)
Thank you in advance!
EDIT:
Passwords are hashed with bcrypt
; for new users that hashed password is immediately used to make a temporary URL from a JWT, a la
jwt.sign( { data: newUser.id }, newUser.login_pass + "-" + newUser.account_created)
which gives something like http://domain.com/activate/eyJkYXRhIjoxMDI1LCJpYXQiOjE1ODU5MzAwNTd9.Y2BYzfc0oETn9kbzQ_ek_0FYTV8WDPoRBT4jmAQeQ68
dynamic_urls
is a really weird name for this.account_activation_tokens
would be much clearer.temporary_urls
because the table also contains temporary URLs for password resetting, but I'm open to suggestions.