Basic Authentication

In this article we’re going to take a look at the steps to create a basic authentication system which will allow you to login and retain state (using PHP sessions) using details which are logged in a table in your MySQL database. This login system will provide you the functionality to login, however leaves a lot to be desired in regards to security - you should research this element and build upon this lab.

Prerequisites

Before we get started you will need the following in place

  1. A working web server

  2. Access to a MySQL database

  3. A table in this database with relevant fields to allow you to authentication a user, user_id, username and password would work 😁

  4. The knowledge to create and edit existing scripts to allow you to submit data to a MySQL database (you can follow our Form Submission guide first if you don’t already have this 😁)

Starting point

In order to get started with this task we need a form to work from, you can create this form by following the Form Submission guide which is also part of this section on developerspace.co.uk. The code we’re going to use in this example you can see below.

login.php

<form action=" " method="POST">

	<label for="username">Username</label>
	<input type="text" name="username" value="">
	
	<label for="password">Password</label>
	<input type="text" name="password" value="">
	
	<button>Login</button>
</form>

Note this file still has the .php file extension, that’s because later we will be adding PHP code to the end of this file.

Note: should be placed in a relevant path within your home area, I would suggest this is within a directory such as authentication or auth. This helps to keep your code organised and will serve you well in terms of security of your web application later down the line.

Login Processing

We now have a basic HTML form, the structure isn’t perfect, it could do with styling, it could do with being formatted so that it works well and fits in within out existing application, however it will serve our main purpose well and that is to allow a user to login to the web application.

Above this we now need to add some PHP, this will carry out some similar activities to what we have already seen throughout this series. Below is a brief summary of what we will code next…

  1. Check the database for a match, using the provided details (username), we will forget about the password here, the why for this point will become apparent shortly.
  2. Compare the information submitted in the user submission form with the data stored in the users account details in the database.
	// create the session
	session_start();
	
	// load the functions file
	include_once('../admin/functions.php');
	$conn = connect_database();
	
	// check that we actually have input
	if($_SERVER['REQUEST_METHOD'] == "POST") {
     
        // we will add our login logic here
        
    }

In the snippet above we have created a new PHP session using the session_start() built-in PHP function. This will be needed later to ensure that the user can remain logged into the system. We also load our external functions file and then called the connect_database function to connect to the database.

Following this we then check to make sure that we are being sent a POST request. This is important as without this line we would process all of the PHP straight away, not even giving the browse the opportunity to show the input fields for username and password.

Check that we have login credentials

We now need to carry out a few basic security measures, these can help to mitigate DoS and DDoS attacks. In this case we’re going to check that we have a username and password, and information has been sent to the server. Without these rules you could click login without entering any login details which is an unnecessary request to the server.

This should go into the section labelled login logic in the code snippet above.

// check we have both a username and a password
		if(!isset($_POST['username']) || $_POST['username'] == '' || 
		!isset($_POST['password']) || $_POST['password'] == '') {
			echo "You need to provide login credentials";
			exit();
		}

This is a simple chunk of code and should be modified further to ensure a greater level of security.

You will start to see elements marked with @todo where there is more for you to do. You need to research how to approach these challenges and add in additional code and functionality to make this your own project.

Consider looking at the Form Validation guide in this series for a starting point on making this form more secure.

Grab the data from the form

Now that we have the basis of the form, we have our Database connection handles and we’ve made sure that a user must at least enter a value for both the username and password before proceeding we can now handle the data sent by the user.

The code snippet below shows a nice efficient method of making this happen.

	// grab the username and password into variables
	// @todo Add Validation
	$username = $_POST['username'];
	$password = $_POST['password'];

In this example we use variable names $username and $password because these are nice and clear, easy to read and because why not 😊

If in the username field I enter John Smith then the value of $username will be John Smith. The same goes for password, if I enter mysupersecurepassword! then $password would be superstrongpassword!. This second field, password, links into our next challenge.

Check for a match

You should already have a table in your database which is storing the details of the users, in this example the table is going to be called login. If you don’t have a table in your MySQL database then you will need to add it now before proceeding. A sample of the structure of this table you can find below.

CREATE TABLE login (
    user_id int AUTO_INCREMENT,
    username varchar(30),
    password varchar(255)
);

Once we have the table we need to check for a match in the table, and there is only one method at the moment with such a basic table structure which will make this possible. That is to match on the username only, consider that we enter the following login details.

Username: joebloggs

Password: securepassword!

Instead of taking into account both of these pieces of information we’re only going to look at the username. The reason we do this is because the user will be entering their username and password in plaintext, in the case of the username this will be stored in plaintext, however the password will not. This means its impossible to get a match on this at the moment.

Let’s take a step back

Okay so we’ve covered a lot of information so far, however let’s take a step back and discuss one of our previous points in more detail. We discuss how the password will not be stored in plaintext, this is because it should be stored securely.

We’re going to use the “industry-grade and battle tested” bcrypt algorithm for this. This ensures that if for any reason somebody did get hold of our database files, backup or live access they can’t see everybody’s passwords.

Running the check

Now that we’ve decided on the algorithm we will use to hash the password we’re going to have a look at finding the record to match first of all.

		$record = $conn->prepare("SELECT * FROM login WHERE username = '$username'"); 
		$record->execute(); 
		$user_result = $record->fetch();

In this snippet we’re simply querying the database for a match where the username matches what the user entered in the login form. Bear in mind that MYSQL does not take into account the case, so joebloggs as a username would work just the same as JoeBloggs.

If there is a match we will receive a result in an array format response, this will be stored in the $user_result variable.

To check that this is a match we need to run this through the built-in PHP password_verify() function, this accepts two parameters as below.

  1. The password entered in the login form
  2. The password from the database result

If these match this function will return a boolean response, true. You can see below how we have handles this using an if statement which you should be familiar with by this point in the series.

// this is the encrypted version
		$encrypted_password_check = password_verify($_POST['password'], $user_result['password']);
	
		// if the user details match
		if($encrypted_password_check) {
		
			$_SESSION['logged_in'] = true;
			$_SESSION['username'] = $username;

		}

// @todo redirect to an admin panel / relevant secure area

One of the key parts of this code is the setting of the $_SESSION super global variable which ensures that we retain the login information when we move throughout the application.

	$_SESSION['logged_in'] = true;
	$_SESSION['username'] = $username;

Full Code Snippet

Below is the full code snippet for this article so you can see the full structure. Remember you can use this for different things, and there are some fundamental flaws, particularly around security with using this method.

<?php
	
	// create the session
	session_start();
	
	// load the functions file
	include_once('../admin/functions.php');
	$conn = connect_database();
	
	// check that we are expecting to receive login details
	if($_SERVER['REQUEST_METHOD'] == "POST") {
		
		// check we have both a username and a password
		if(!isset($_POST['username']) || $_POST['username'] == '' || 
		!isset($_POST['password']) || $_POST['password'] == '') {
			echo "You need to provide login credentials";
			exit();
		}
		
		// grab the username and password into variables
		// @todo Add Validation
		$username = $_POST['username'];
		$password = $_POST['password'];
		
		
		$record = $conn->prepare("SELECT * FROM login WHERE username = '$username'"); 
		$record->execute(); 
		$user_result = $record->fetch();
		
		// this is the encrypted version
		$encrypted_password_check = password_verify($_POST['password'], $user_result['password']);
		
		if($encrypted_password_check) {
		
			$_SESSION['logged_in'] = true;
			$_SESSION['username'] = $username;
			
			echo $_SESSION['logged_in'];
			echo $_SESSION['username'];
		}

	}

?>

<form action=" " method="POST">

	<label for="username">Username</label>
	<input type="text" name="username" value="">
	
	<label for="password">Password</label>
	<input type="text" name="password" value="">
	
	<button>Login</button>
</form>