2

I tried doing something like this:

$user = $wpdb->get_row('
    SELECT * 
    FROM ' . $wpdb->users . ' 
    WHERE user_pass = "' . wp_hash_password('password') . '"'
);

But the wp_hash_password function generates a different string from the one in the database, is it possible?

What I'd like to do is have a custom form in my template that just asks for a password (think of it like the username/pwd screen to the WP admin area without the username) so I'd hash whatever the user inputs, compare it with my DB and if it matches take that user and log him in.

6
  • 1
    Ignoring the objection for doing it at all, why do you think the password in the DB was generated with wp_hash_password? what value do you expect to be there and what value do you get? Commented Jan 22, 2013 at 13:59
  • Very very bad man
    – Adam
    Commented Jan 22, 2013 at 14:33
  • @MarkKaplun I though that's they function WP used when creating a new user but it looks like they do something different. If I hash a string with wp_hash_password it generates a random string every time it runs Commented Jan 22, 2013 at 15:36
  • 1
    I agree with everyone else that says this is a terrible idea. That said, look at wp_check_password documentation for how to match passwords.
    – Dan
    Commented Jan 22, 2013 at 16:08
  • I know it's not a very good idea but it's a request from a client and I just wanted to know if it was possible. I checked wp_check_password and I think it might work, I can loop through the users table and check every hash against the string the user inputs and if something matches then return that user's ID. I'll give it a go. Commented Jan 22, 2013 at 16:27

3 Answers 3

10

Password is not unique all the time.

According to worst password statistics, password is the most used Password of all time.

I'm pretty sure some of your users too use that password.

So multiple rows will contain the same hash. Hence its not possible.

By the way, this is a weird question.

enter image description here

10
  • 3
    And even different passwords can result in identical hashes. Hashes are by their nature not collision safe.
    – fuxia
    Commented Jan 22, 2013 at 6:13
  • That was just an example, I just want to know if it's possible to login a user by just asking the password, there should be a way to hash the text string to be the same as in the DB (kind of how the wp_signon function works). I guess hashes can be the same even if the password is different but really how likely is this scenario considering passwords have ~30 characters? Commented Jan 22, 2013 at 6:14
  • You enforce 30 character passwords? Are you confusing the hash with the password? The hash might have ~30 characters but the pass could still be "hi".
    – s_ha_dum
    Commented Jan 22, 2013 at 6:23
  • Giri, can you provide the link for the statistics?
    – brasofilo
    Commented Jan 22, 2013 at 9:32
  • @brasofilo Updated answer with statistics image Commented Jan 22, 2013 at 12:23
3

Per the comments I'm going to answer a paraphrased question - "How to make a login form which shows only the password field in most cases".

The answer is to store the user name in a very long term cookie (a year?) every time the user logins.

function wpse82578_set_user_cookie($logged_in_cookie, $expire, $expiration, $user_id, $state) {
  if ($state == 'logged_in') { // user has logged in - store his name in a 'username' cookie
    $user = get_user_by( 'id', $user_id );
    setcookie('username', $user->user_login, time() + 365*24*60*60, COOKIEPATH, COOKIE_DOMAIN);
  }
}
add_action('set_logged_in_cookie', 10,5);

Now in you PHP code you can check if the cookie is set and show or hide the user name field in your form.

function wpse82578_echo_login_form() {
   ...
   if (isset($_COOKIE['username'])) { // already know the user name, no point in asking for it again so just put it as hidden field
     <input type="hidden" name="log" value="<?php esc_attr($_COOKIE['username'])?> />
   else { // show the field+label, ripped from wp_login_form
        <p class="login-username">
            <label for="' . esc_attr( $args['id_username'] ) . '">' . esc_html( $args['label_username'] ) . '</label>
            <input type="text" name="log" id="' . esc_attr( $args['id_username'] ) . '" class="input" value="' . esc_attr( $args['value_username'] ) . '" size="20" tabindex="10" />
        </p>
    }
}

No warranties for this code, but I think it is the best approximation to what you want without sacrificing security and messing with the WordPress user system.

0

Here's what I ended up doing in case someone else need a similar functionality:

// Simple text password
$client_password = $_POST['client_pwd'];

$users = get_users();

// Iterate over all users and see if the password matches
foreach ($users as $user) {
    // If it matches log the user in
    if (wp_check_password($client_password, $user->user_pass)) {
        $user = wp_signon(
            array(
                'user_login'    => $user->user_login,
                'user_password' => $client_password
            )
        );

        if (!is_wp_error($user)) {
            // Redirect or do something else
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.