PHP password_verify Returning False When Retrieving Hashed PW from Database

I've scoured the threads inside and outside of SO, but nothing has solved the issue.

Background: Creating a small login system with PHP, Wordpress, and ACF (Advanced Custom Fields). Upon saving of the Post containing the Password, the password gets hashed, and the value replaced in the database. So far so good (as far as I can tell). When a user visits the login page, submits a password-attempt, the validation php file calls the Wordpress API, retrieves the stored-hashed PW, and then runs password_verify. Every time this runs, it returns false. Code below...

    $pw_submit = $_POST['pw-submit'];

    //Call WP API
    $urlPrefix = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ?
    'https' : 'http';
    $siteURL = $urlPrefix . "://" . $_SERVER['SERVER_NAME'];
    function callAPI($method, $url, $data){
        $curl = curl_init();
        $url = sprintf("%s?%s", $url, http_build_query($data));

        // OPTIONS:
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: 
            application/json'));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        // EXECUTE:
        $result = curl_exec($curl);
        if(!$result){die("Connection Failure");}
            curl_close($curl);
            return $result;
    }

    $get_data = callAPI('GET', $siteURL . '/wp-json/acf/v3/pages/25', false);
    $response = json_decode($get_data, true);
    $db_password = $response[acf][portal_password];        

    if( password_verify( $pw_submit, $db_password) ){
        echo "Well that worked";
    }
    else{
        echo "No it didn't";
    }

Even if I copy/paste the hashed password over and try to verify, it still returns false...

    $hash = '$2y$10$2/PuBIYuhEJ69fSc2/ae.OOVr4nMrpKu.9ahRm90TuSBu0EJulWki';
    $verify = password_verify('foobar', $hash);
    var_dump($verify);

...it returns bool(false).

The ONLY way password_verify ever returns true is if I create the hashed-password and verify it right away. So in the validation script...

    $pw_hash = password_hash('foobar', PASSWORD_DEFAULT);
    $verify = password_verify('foobar', $pw_hash);
    var_dump($verify); // Returns TRUE

I've checked the database and made sure the table cell is holding the entire hash (when I var_dump the pulled value, I get a 60 character string). I've made sure there are no empty spaces before/after by using trim(). I've tried replacing the containing double-quotes containing the hashed-string with single-quotes. I have no idea what's missing/going wrong. Any help/guidance is GREATLY appreciated. Thanks!

UPDATE So the error in this was that I had forgotten to update a variable when fixing a previous issue. For those who might stumble upon this, the original issue was that Wordpress was running my hashing script twice, resulting in a hash of the first hashed password. So always check what wordpress is actually doing. Also, one thing I ran into was using the ACF get_field() to grab the unhashed password, but because I was using the wp_insert_post_data() filter, I was actually grabbing an old/current value, instead of getting the new/input password. Fixed this by using the 'acf/save_post' filter. Thank you everyone for the help!

1 answer

  • answered 2018-10-09 16:29 Brxxn

    $db_password = $response[acf][portal_password]; doesn't have properly formatted indexes. Use $db_password = $response['acf']['portal_password']; instead.

    Because of this error, password_verify($pw_submit, $db_password) is verifying the users entered password with the variable $db_password which doesn't contain any information.