Can't get password_verify() to work

I’m fairly new to PHP even though I’ve been coding for 25+ years. The issue I’m having is my login script. I know it seems pretty easy and straight-forward but I’m hung up on the password_verify() function. I’ve hashed my password in the database table. Below is the code that I copied from “Chatgpt.com” with changes reflecting my varialbe/table names.

Thanks,
Blake

<?php
require "dbconnection_pdo.php";

// Start session
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $username = htmlspecialchars($_POST['username'] ?? '');
    $password = htmlspecialchars($_POST['password'] ?? '');

    // Query to find the user
    $sql = "SELECT password, user_handle FROM food.users WHERE username = :username";
    $stmt = $pdo->prepare($sql);
    $stmt->execute(['username' => $username]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    echo $password . "<br>";
    echo $user['password'];

    if ($user && password_verify($password, $user['password'])) {
        $SESSION['handle'] = $user['user_handle'];
        header('Location: index.php');
        exit();
    } else {
        echo "<script>document.getElementById('msg').innerHTML = 'Invalid login credentials!';</script>";
    }
}

How do you know it’s the password_verify() that isn’t working?

A bunch of do’s and don’ts for the posted code -

  1. Don’t apply htmlspecialchars() (or more shortly htmlentities()) to the input data you are using in your post method form processing code. These are OUTPUT functions. They are used on data being output in a html context, right before it is output.
  2. Don’t use default empty strings for expected and ‘required’ inputs. Once the form has been submitted, these two inputs will be present. If the are not, it’s either due to a programming mistake or someone not submitting your data to your form processing code. In these cases you would want to see/log any related errors. If a ‘required’ input is empty, you should never get to the point of using the data values.
  3. Don’t copy variables to other variables for nothing.
  4. Do keep the form data as a set in a php array variable, such as $post.
  5. Do trim all input data, mainly so that you can detect if all white-space characters were entered
  6. Do validate all inputs, storing user/validation errors in an array using the field name as the array index.
  7. After the end of the validation logic, if the array holding the user/validation errors is empty, use the submitted form data.
  8. If you set the default fetch mode to assoc when you make the database connection, you won’t need to specify it in each fetch statement.
  9. Don’t lump together multiple values in a conditional statement as that makes it harder to debug problems or log instances of bad usernames and/or passwords being tried.
  10. If the username/password is incorrect, add the ‘Invalid login credentials!’ message to the array holding the user/validation errors.
  11. After using the submitted form data, if there are no user/validation errors, perform a redirect to the exact same URL of the current page to cause a get request for that page. This will prevent the browser from resubmitting the form data should that page get browsed back to or reloaded, where someone can use the browser’s developer tools to see what the username/password is.
  12. If you want to display a one-time success message, store it or a flag value in a session variable, then test for, display the success message, and clear the session variable at the appropriate location in the html document.
  13. If there are user/validation errors at item #7 or #11 on this list, the code will continue on to display the html document, where you will test for and display any user/validation errors, either all at once or adjacent to the field they correspond to, and redisplay the form.
  14. Any dynamic value you output in a html context needs to have htmlentities() applied to it to help prevent cross site scripting.

Since I am new to PHP, would you mind just taking my code and making the corrections?

Thank you

The list of points help with security, provide a better user experience, move functionality to the correct place, and remove unnecessary clutter.

Before you worry about them you need to find out why the code isn’t working now. Answer the question as to why you think password_verify() isn’t working? Without this feedback from you the problem hasn’t been narrowed down to any specific thing. It’s currently somewhere between the markup for the registration form and the end of the posted login form processing code, including whatever the index.php page is doing, what the database connection options are, what the database table definition is, and what php version you are using.

If you want someone to critique all the code, you will need to post all of it, less the database credentials.

I actually went with a little more primitive way using sodium encryption/decryption. It’s working now. Thank you for your suggestions.

Hello Blake,

AI coding at your own risk. I say that because I have had to correct AI-generated snippets, and I’m learning PHP with way less coding experience than you. You can probably notice oddness in code better than me, though.

password_hash may be what you need to use when storing the passwords to the database: Here’s an example from my user registration script:

$hashed_password = password_hash($password, PASSWORD_DEFAULT);

PASSWORD_DEFAULT will save you from having to update encryption methods going into the future.
The manual page: https://www.php.net/manual/en/function.password-hash.php

Sponsor our Newsletter | Privacy Policy | Terms of Service