in reply to Steps for the migration to hashed passwords

2. superdoc: activate_user( Int $user_id, Str $activation_hash )

I would accept a password as input here, rather than generate one as output. The password will be active long term (until the user changes it - possibly forever). The outbound page might be cached. While the inbound request might also be intercepted, it is less likely to be cached, reducing the exposure a little.

The new password could be an optional parameter. If not present with an acceptable value, display a form to enter the password. If an acceptable password is given, generate and store the hash, etc., then forward the user to the login page.

5. User settings

Just a nit: I guess this is the edit profile page.

The old password should be required here, so that a stolen login cookie / session is not sufficient to reset the password.

The only place it should be possible to set a new password without providing the old password is on the activation page. Access to this is restricted by the time limited activation hash sent by email only to the account owner.

6. # Everything/HTML.pm#::confirm_user

Maybe I don't understand what this is, in which case, just ignore the following. I am assuming this is user authentication on every page.

Requiring a password on every page increases the exposure of the password. Would it not be better to put a session key in the login cookie and authenticate the user with this session key? Ideally, the password would only be entered at the activation, login and password reset pages. Ideally, some day, these three pages would be SSL.

So, login goes like this:

my $ok; $hash = &generate_hash( $USER, $passwd ); # ... confirm via hash $ok = $hash eq $USER->{passwd_hash}; # if the hash-compare failed and the user still has a password, use th +at: if (! $ok and defined $USER->{passwd}) { $ok = $passwd eq $USER->{passwd} } if($ok) { # generate session key # save session key in ??? (user or session table) # send login cookie with session key - # for current browser session, # or a permanent one for cowboys }

Non login pages would then authenticate the user by comparing the provided session key with the stored key, without exposing the password.

Replies are listed 'Best First'.
Re^2: Steps for the migration to hashed passwords
by Corion (Patriarch) on Aug 12, 2009 at 21:24 UTC

    Regarding activate_user(), I don't see what accepting a password (as a GET parameter upon page display) would bring. Making the user choose a fresh password (and otherwise suggesting one) upon activation makes sense though.

    The user edit change, especially requiring the old password, makes sense, but isn't important while moving to password hashes. But it should be possible to also put it in while we're looking at the code :).

    Everything/HTML.pm::confirm_user is the code called for every page that looks at whether the supplied cookie actually matches a hash of your credentials. So your password is not stored in the cookie, but basically you get a session key, albeit one with unlimited validity. Your fallback to doing the validation through the password directly is more or less what's done now, except that the cookie is using a hash, and the same hash is rebuilt from the password.

    Thanks for looking at the changes and giving them critical thought!