Changing passwords
In this section, we'll go over how to provide a way for users to change their account password. We recommend checking out our lesson about a user login if you aren't sure how to start.
The code for this version will be written in a procedural method.
Requirements
Refer to the Get Started section to know what you need to use this tutorial. You must also have an understanding of HTML and how a web page is constructed.
We'll go through this assuming you know how to make an HTML form, use a MySQL database and understand the users's $_SESSION
variables that we used in our lesson about a user login.
Prerequisites
To use this tutorial, we recommend that you use our other lesson, our User log-in and log-out.
Contents
The MySQL database
To allow a user to modify their password, we'll need the database holding their information. We will be using a MySQL database created in previous lessons, including our lesson about a user login. Feel free to use any kind with which you are familiar as long as you can adapt our code to fit correctly.
We'll use the database created in our other lesson about user registration. This is the table we will be using to log in a user.
Table: users
Column | Type | Description |
---|---|---|
userID | INT (11) | This will be the primary key. It is a unique ID number assigned to each individual user. It should be set to increment automatically. |
Varchar (250) | This will hold the user's email address. They'll use this to log into your site. | |
password | Text | The user's password will be encrypted. |
salt | Int (11) | "salt" will be used to encrypt they user's password. |
isDeleted | Bool | A TRUE/FALSE value that will be used to tell if a user has canceld there account or has been blocked. |
timestamp | Timestamp | A time stamp, provided by the database, about time the account was created or last updated. |
If you've successfully done our other lesson, User registration, you should have rows in your table that look similar to this:
userID | Password | Salt | isDeleted | timestamp | |
---|---|---|---|---|---|
1 | user@website.com | alksjd98f7a3lkj23kjlafg135ge | 1611081310 | 0 | 2021-01-19 01:35:10 |
2 | user2@website.com | iooqiqur798gn3l523nkavf98u | 1611081612 | 0 | 2021-01-19 01:40:22 |
3 | user3@website.com | vx63iv73oulvkj456209v8vj34 | 1611081914 | 0 | 2021-01-19 01:45:34 |
We will create a form to change the password, then compare the submitted current password against that stored in the database and update it with the new password if things match.
The HTML form
Create a PHP web page file with a form for your users to change their password.
<html> <head> <title>Change password</title> </head> <body> <h1>Change password</h1> <form action="" method="post"> <p> <label for="current_password">Your current password</label> <br/> <input type="password" name="current_password" id="current_password" /> </p> <p> <label for="new_password">Your new password</label> <br/> <input type="password" name="new_password" id="new_password" /> </p> <p> <button type="submit">Change password</button> </p> </form> </body> </html>

With that form, we'll be able to gather the user's current password and new password. Leave the method="post"
so the user's submitted data won't be displayed in the URL. We're leaving the action=""
blank so the PHP can remain on just this page.
Beginning the PHP
Since we want this page to be accessed by only logged-in users, we must start and verify the $_SESSION
values. Refer to our lesson about setting restrictions for information.
The array $_POST
will hold the user's submitted information. It is a global variable and is available on the page whether the user has submitted the form or not. To prevent this from processing an empty $_POST
, we'll set up a simple if()
conditional about the HTML.
<?php session_start(); // Is the user logged in? if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){ header('Location: /login.php'); } // Did the user submit the form? if(!empty($_POST)){ // Process the form } ?> <html> [...]
That conditional will prevent anything from happening unless the form is submitted. Next, we'll take the variables out of the $_POST
array for use.
Getting the $_POST variables
Once the form is submitted, the $_POST
array will be holding the variables from it. The form we have will carry two variables, $_POST['email']
and $_POST['password']
.
<?php session_start(); // Is the user logged in? if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){ header('Location: /login.php'); } // Did the user submit the form? if(!empty($_POST)){ // Process the form $current_password = $_POST['current_password']; $new_password = $_POST['new_password']; } ?> <html> [...]
Now we have the variables from the $_POST
array in separte variables. We could work through the whole process with them in the $_POST
array, but htis simplifies it. Next, let's make sure both fields are valid.
Validating the form fields
We want to avoid bad data as often as possible. So, let's make sure the user has submitted real, valid data. Neither the current password nor the new password may be left blank.
PHP has two functions that we will be using. We'll use the function trim()
to see if the password was left blank or with only spaces. We'll use function filter_var()
to make sure the email address is formatted like an email address. We'll use a conditional if()
to judge whether or not the process should continue.
<?php session_start(); // Is the user logged in? if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){ header('Location: /login.php'); } // Did the user submit the form? if(!empty($_POST)){ // Process the form $current_password = $_POST['current_password']; $new_password = $_POST['new_password']; $check_current_password = trim($current_password); $check_new_password = trim($new_password); if($check_current_password != '' && $check_new_password != ''){ // Continue the process } else { $error = 'Please provide both your current password and your new password.'; } } ?> <html> [...]
The function trim()
removes any spaces at the start and end of the string in $current_password
and $new_password
.
Notice the variable, $error
. We'll use that later on to tell the user something went wrong. If everything went well, we'll get started with a connection to the database.
Connecting with the database
If the user's current and new passwords checked out, let's connect to the database and prepare to change their password. We'll use the PHP built-in class MySQLi
to do it. Let's take a look into the if()
conditional that approved the email address and password.
if($check_current_password != '' && $check_new_password != ''){ // Continue the process // What's the address of your database? $database_host = 'localhost'; // What's the username to connect? $database_user = 'root'; // What's the password for that user? $database_password = 'password'; // What's the name of the database? $database = 'social'; // User the MySQLi class to connect to database $mysqli = new mysqli($database_host, $database_user, $database_password, $database); $current_password = $mysqli->real_escape_string($current_password); $new_password = $mysqli->real_escape_string($new_password); // Always close the database connection $mysqli->close(); }
Once we had a connection to the database, we were able to use a function built into the class MySQLi
, real_escape_string()
. That function analyzed the strings and cleaned them up, if necessary, to protect the database from queries a user might be sending. Even though we validated the username and password, We should still sanitize them.
Getting the user information
Now that we know the user has submitted valid data, we want to compare it against the info in the database. We'll query for information about the user depending on the email address they submitted.
if($check_current_password != '' && $check_new_password != ''){ /* Database connection stuff */ $sql = "SELECT password, salt FROM users WHERE userID='" . $_SESSION['userID'] . "'"; $query = $mysqli->query($sql); $pass = $query->fetch_assoc(); // Always close the database connection $mysqli->close(); }
The query is asking for the encrypted password and salt
from the user with an ID number matching that in their $_SESSION
. The variable $_SESSION['userID']
was generated in the log-in process. Then, we're using the MySQLi
class function, fetch_assoc()
, to get that information into an array.
The variable, $pass
, is now an array containing the user's encrypted password and salt
. If you want to see what is in $pass
, enter print_r($pass);
under the variable. The array looks similar to this:
Array ( [password] => alksjd98f7a3lkj23kjlafg135ge [salt] => 1408705391 )
Comparing the passwords
In a different lesson, User registration, we went over a way to encrypt the user's password by salting it with another variable. We stored the salt
in the database next to the encrypted password. Let's attach the salt
to the password the user submitted, encrypt it, and then compare it against the encrypted password in the database.
To get to the stored salt
, we need to use $user['salt']
. To get to the stored password, we need to use $user['password']
.
if($check_password != '' || $check_email !== FALSE){ /* Database connection stuff Table query */ $pass = $query->fetch_assoc(); $salt = $pass['salt']; // Does their $current_password, while encrypted, match their database password? $encrypt_current_password = sha1($current_password . $salt); if($encrypt_current_password == $pass['password']){ // Password matches. Continue to change password. } else { $error = 'Incorrect information. Please try again.'; } // Always close the database connection $mysqli->close(); }
Just as we did in a different lesson, User registration, encrypted the password the user submitted by salting it with another variable, the one provided by the database, and compared the encrypted version.
If the encrypted versions match, the user is valid and we should allow them in to change their password.
Changing the password
To change the user's password, we need to update their row in the database table users
. We need to make new salt
and encrypt their new password.
if($encrypt_current_password == $pass['password']){ $new_salt = time(); $encrypt_new_password = sha1($new_password . $new_salt); $sql = "UPDATE users SET password='" . $encrypt_new_password . "', salt=" . $new_salt . " WHERE userID=" . $_SESSION['userID']; $query = $mysqli->query($sql); $error = 'Successfully updated your password.'; } else { $error = 'Incorrect information. Please try again.'; }
We have updated the user with userID
equal to the $_SESSION['userID']
to have a new password with new salt
.
What if there were errors or success?
The user may have submitted invalid data, their password may not have matched that in the database or the could have completed it successfully. Let's use the $error
variable we created to deliver the message on the web page.
<html> <head> <title>Change password</title> </head> <body> <h1>Change password</h1> <?php if(isset($error)): ?><?php echo $error; ?>
<?php endif; ?> <form action="" method="post"> <p> <label for="current_password">Your current password</label> <br/> <input type="password" name="current_password" id="current_password" /> </p> <p> <label for="new_password">Your new password</label> <br/> <input type="password" name="new password" id="new_password" /> </p> <p> <button type="submit">Change password</button> </p> </form> </body> </html>
All the code
<?php session_start(); // Is the user logged in? if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){ header('Location: /login.php'); } // Did the user submit the form? if(!empty($_POST)){ // Process the form $current_password = $_POST['current_password']; $new_password = $_POST['new_password']; $check_current_password = trim($current_password); $check_new_password = trim($new_password); if($check_current_password != '' && $check_new_password != ''){ // Continue the process // What's the address of your database? $database_host = 'localhost'; // What's the username to connect? $database_user = 'root'; // What's the password for that user? $database_password = 'password'; // What's the name of the database? $database = 'social'; // User the MySQLi class to connect to database $mysqli = new mysqli($database_host, $database_user, $database_password, $database); $current_password = $mysqli->real_escape_string($current_password); $new_password = $mysqli->real_escape_string($new_password); $sql = "SELECT password, salt FROM users WHERE userID='" . $_SESSION['userID'] . "'"; $query = $mysqli->query($sql); $pass = $query->fetch_assoc(); $salt = $pass['salt']; // Does their $current_password, while encrypted, match their database password? $encrypt_current_password = sha1($current_password . $salt); if($encrypt_current_password == $pass['password']){ $new_salt = time(); $encrypt_new_password = sha1($new_password . $new_salt); $sql = "UPDATE users SET password='" . $encrypt_new_password . "', salt=" . $new_salt . " WHERE userID=" . $_SESSION['userID']; $query = $mysqli->query($sql); $error = 'Successfully updated your password.'; } else { $error = 'Incorrect information. Please try again.'; } // Always close the database connection $mysqli->close(); } else { $error = 'Please provide both your current password and your new password.'; } } ?> <html> <head> <title>Change password</title> </head> <body> <h1>Change password</h1> <?php if(isset($error)): ?><?php echo $error; ?>
<?php endif; ?> <form action="" method="post"> <p> <label for="current_password">Your current password</label> <br/> <input type="password" name="current_password" id="current_password" /> </p> <p> <label for="new_password">Your new_password</label> <br/> <input type="password" name="new_password" id="new_password" /> </p> <p> <button type="submit">Change password</button> </p> </form> </body> </html>
Contact us
Questions or problems? Want to contribute to this tutorial or others?