The following list details (IMO) the steps necessary to move from plaintext passwords to storing hashed passwords, and also moving the infrastructure (password resets, initial sign-up etc.) to accomodate hashed passwords. All steps can be taken without interruption. I'm not sure if my approach of using hashes for "activation" and then resetting the password only when that "activation" hash is submitted, together with the appropriate user id in the appropriate timeframe is sensible.

Discussion of the approach and/or the other changes is very much welcome, as is a discussion of what I named things. I'm bad at naming things, especially.

  1. Table pending_activations ("new user entries", "password reset entries")
    1. user_id (for password resets)
    2. username (for new user signups)
    3. activation_hash
    4. expires default now()+12hr (MySQL 5.0, which we use, does not allow functions for default values :()
  2. Add a password hash column to the user table
  3. superdoc: activate_user( Int $user_id, Str $activation_hash )
    1. check user_id+activation_hash in pending_activations
      select user_id from activate_user where user_id = :$user_id and activation_hash = :$activation_hash and expires > now()
    2. generate fresh password
    3. hash = &generate_password_hash( $USER, $passwd )
    4. store fresh password in user table
    5. store fresh hash in user table
    6. store fresh password in $USER
    7. send login cookie that's valid for this browser session
    8. display fresh password to user
    9. display link to "Log me in and give me a permanent cookie" (expiry=never)
  4. htmlcode: generate_password_hash( $USER, Str $passwd )
    1. generate hash from password+username+secret sauce
  5. htmlcode: generate_activation_hash( $USER, Int expiry )
    1. generate random hash
      INSERT into pending_activations user_id, hash, expiry
    2. return hash
  6. User settings user edit page:
    1. hash = &generate_password_hash( $USER, $passwd )
    2. store hash in user table
    3. set cookie to hash
  7. Everything/HTML.pm#::confirm_user
    $hash = &generate_hash( $USER, $passwd ); # ... confirm via hash my $ok = $hash eq $USER->{passwd_hash}; # if the hash-compare failed and the user still has a password, us +e that: if (defined $USER->{passwd}) { ... confirm via passwd }
  8. htmlcode: generate_activation_link( $USER )
    1. hash = &generate_activation_hash( $USER )
    2. return abs_url($settings{site_url}/?node_id=activate_user;user_id=$USER->{id};hash=$hash)
  9. Activation

    1. add hash column to user table
    2. populate hash column by generating the hash from the passwd if it's not NULL
  10. new user mail (975)
    1. don't display password
    2. display activation_link resp. change the template to generate the activation link
  11. Password Mail (2514):
    1. don't display password
    2. display activation_link resp. change the template to generate the activation link
  12. Deactivation of passwords
    1. set passwd to NULL
    2. remove code for storage of passwd from activate_user()
    3. drop passwd column from user table after all users have been migrated (select count(user_id) where passwd is not null) == 0

Update: Corrected node links, added topics as per ig's reply below

Further Update: Found out that MySQL doesn't support functions in default values. Changed names to fit reality.


In reply to Steps for the migration to hashed passwords by Corion

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.