5 ms·
#Start a password reset @user = User.find_by_email @user.update_attribute :password_reset_nonce, rand(16 ** 16).to_hex #mail them the password reset emai
by patio11 14y ago
#Start a password reset
@user = User.find_by_email
@user.update_attribute :password_reset_nonce, rand(16 ** 16).to_hex
#mail them the password reset email
#Look up a user for a password reset
@user.find_by_password_reset_nonce params[:password_reset_nonce]
#if nil, above line returns random user on some databases. Oops.
session[:user_id] = @user #Logs in user
#We assume if they know the nonce that proves they own email.
redirect_to passwordReset_url
I've elided additional code which might theoretically be used to make the nonce expire and to prevent re-use for brevity, but it's possible that neither of these measures would fix the issue.
Bugs like this one always make me think "There but for the grace of God go I."
- jmillikin 14y agoIt's the "if nil, above line returns random user on some databases" I'm curious about. What databases behave thus? It's a very problematic behavior.
- Xylakant 14y agoIt may be evaluated as "SELECT * FROM USERS WHERE password_reset_nonce IS NULL". If your password_reset_nonce field may contain null values, this will fetch the first row of those it finds. Some databases show quasi-random behavior when fetching that row.
- lacerus 14y agoto_hex does not seem to be in the standard library, but these will work and are rather elegant to get a short random string. Thanks, Patrick! rand(16**16).to_s(16) rand(16**16).to_s(36)
- earless1 14y agohttp://www.ruby-doc.org/stdlib-1.9.3/libdoc/securerandom/rdoc/SecureRandom.html http://www.ruby-doc.org/stdlib-1.9.3/libdoc/securerandom/rdo...
- t-crayford 14y agoDoing params.fetch(:password_reset_nonce) would get you out of that nil issue. Doing fetch is generally good practice, especially on params, as often without the right params you can't do anything anyway and should be bailing out with a 404 or another error code.