Level: Intermediate 

Requirements: PHP, MySQL knowledge. Local or Server hosting with suitable PHP / MySQL environment enabled. 

Overview

In this series we’re going to build a basic, boring yet necessary system – a login system. Powered by PHP & MySQL database backend and password encryption. 

Whether you’re creating a social network, SaaS app for web, or even a mobile app – the login system is a fundamental part of your user and app experience. And it’s one of the most boring, arduous and mind-numbing pieces of coding you can do. 

Hence, I’ve decided instead of routinely coding up a login system, to create a boilerplate system which can be used for any project, while taking the opportunity to hopefully teach you how to do the same so you can get a jump start on your projects. If you cba to follow and just want a system to download, I’ll put up a link so you can download the complete script with all the files for you to use in your own project. 

At the end of this project series, you should be able to build your own login system, complete with (some) knowledge on how to encrypt your users password data. 

You’ll need to be familiar with PHP and MySQL. If you’re not, then I recommend you check out some starter tutorials / explainer videos to familiarise yourself as we’ll be jumping straight into the core work. 


Part 1 – Database & Config File

We’re going to make 1 table called “app_users”. This will hold the basic information such as a unique user id, their name, email and password (encrypted). If you want to add more information such as last login date, 2 factor auth systems and devices, then you’ll need to add more details as part of your schema. 

Copy and paste the following SQL code into PHPMyAdmin SQL Editor to create the table. 

DROP TABLE IF EXISTS `app_users`;
CREATE TABLE `app_users` (
  `uuid` varchar(256) NOT NULL,
  `fullName` varchar(100) DEFAULT NULL,
  `email` varchar(256) DEFAULT NULL,
  `password` varchar(30) DEFAULT NULL,
  `dateCreated` datetime DEFAULT NULL,
  PRIMARY KEY (`uuid`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Next, 

  1. Create a PHP file called db-config.php and save into your local or server directory. This will be our connection to the database, enabling our app to talk to our database. 
  2. Copy and paste the following php code into db-config.php
<?php

$host = "XXXXXX";
$user = "XXXXX";
$password = "XXXXX";
$database = "XXXX";
$port = null;
$mysqli = mysqli_connect($host, $user, $password, $database);
if ($mysqli-&gt;connect_error) {
    die("Connection failed: " . $mysqli-&gt;connect_error);
}

?&gt;

Change the details in the host, user, password and database to your own. 


Part 2 – User Registration

Now we’ve got the database to begin holding our data, we need to create a page which allows us to capture the data. 

  1. Create a new file called register.php 
  2. Copy and paste the following code into the file: 
<?
include 'db-config.php';

$message = '';

if(isset($_POST['inputName']))
{
  $inputName = $_POST['inputName'];
	$inputEmail = $_POST['inputEmail'];
  $inputPassword = $_POST['inputPassword'];

	$dateCreated = date('Y-m-d H:i:s');

  $bytes = random_bytes(20);
  $uuid = (bin2hex($bytes));

	$pwd = password_hash($inputPassword, PASSWORD_BCRYPT);

  $sql = "SELECT * FROM app_users WHERE email = '$inputEmail'";
	$result = mysqli_query($mysqli, $sql);

  if(mysqli_num_rows($result) &gt; 0) {
		$message = "Hey! Looks like there is already an account associated with this email address. Try logging in or requesting a new password";
	} else {
	$sql1 = "INSERT INTO app_users (uuid, fullName, email, password, dateCreated) VALUES ('$uuid', '$inputName', '$inputEmail', '$pwd', '$dateCreated')";
	if(mysqli_query($mysqli, $sql1)){
		$message = "Successfull";
        header('Location: login.php');
	} else {
	echo "Error" . $sql. "<br /&gt;" . mysqli_error($mysqli);
	}
}

}

?&gt;
<!doctype html&gt;
<html lang="en"&gt;
  <head&gt;
    <meta charset="utf-8"&gt;
    <meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    <meta name="description" content=""&gt;
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"&gt;
    <meta name="generator" content="Hugo 0.79.0"&gt;
    <title&gt;Hypermind</title&gt;
    <!-- Bootstrap core CSS --&gt;
    <link href="https://assets.hypermind.xyz/bootstrap/assets/dist/css/bootstrap.min.css" rel="stylesheet"&gt;

    <style&gt;
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }
    </style&gt;


    <!-- Custom styles for this template --&gt;
    <link href="https://assets.hypermind.xyz/bootstrap/css/signin.css" rel="stylesheet"&gt;
  </head&gt;
  <body class="text-center"&gt;

<main class="form-signin"&gt;
  <form name="register" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?&gt;"&gt;
    <img class="mb-4" src="http://assets.hypermind.xyz/bootstrap/assets/brand/hypermind-logo.svg" alt="" width="100" height="100"&gt;
    <h1 class="h3 mb-3 fw-normal"&gt;Register</h1&gt;

    <label for="inputName" class="visually-hidden"&gt;Full Name</label&gt;
    <input type="text" id="inputName" name="inputName" class="form-control" placeholder="Full Name" required autofocus&gt;

    <label for="inputEmail" class="visually-hidden"&gt;Email address</label&gt;
    <input type="email" id="inputEmail" name="inputEmail" class="form-control" placeholder="Email address" required&gt;

    <label for="inputPassword" class="visually-hidden"&gt;Password</label&gt;
    <input type="password" id="inputPassword" name="inputPassword" class="form-control" placeholder="Password" required&gt;

    <button class="w-100 btn btn-lg btn-primary" type="submit"&gt;Sign Up</button&gt;
    <p class="mt-5 mb-3 text-muted"&gt;© 2021</p&gt;
  </form&gt;
</main&gt;



  </body&gt;
</html&gt;

You should have a page which looks something like the below: 

Let’s break down this script in more detail. 

We’re creating the front end which allows users to come onto a page and add their details to register with our service. We’re using the Bootstrap themes which helps us build and iterate pages quickly. 

Sign Up Button

The magic happens when we click or tap on the “Sign Up” button. If you look at the Form Action field, we’re invoking a PHP SELF action. 

PHP SELF is a function which returns the current script being executed. In plain English, this means we’re telling the form to submit the data to itself (i.e. refresh the page). 

Our script is listening for the POST action and will take the details entered in the form to populate into the database. 

Date

We’re capturing the date the user signed up using a system function date(‘Y-m-d H:i:s’); which will output the date and time the user registered. 

Unique User ID

Each user is assigned a unique user id, which we’re creating using a function borrowed from this answer on Stack Overflow [PHP: How to generate a random, unique, alphanumeric string for use in a secret link?]. This function generates cryptographically secure random bytes which can reduce the chances of duplication and throw an error. 

Password Security/ Encryption

The password_hash() function is used to encrypt the password entered by the user. This function creates a new password hash using a one-way hashing algorithm. As this is a one-way hash, it becomes virtually impossible to see the password string of the user unless by brute-force. We’ll store this hash value in the database. 

Storing the Data 

Line 19 runs a quick check to ensure we’re only allowing a user to register their email address once. I.e. we’re maintaining the unique values in the database.  

If the algorithm finds a record exists, we chuck out an error message in the $note variable, which lets the user know their email address is already registered, else – we continue and INSERT the data into the table and, if successful, redirecting the user to a welcome / login page.


Part 3 – Login 

In this section we’re going to create the login script which checks whether the user email and password match with what we have stored, and if so – sets a cookie and lets the user enter the secure sections of the site. If we can’t find a match, it’ll reject the user and prompt them to register. 

Create a new file called login.php and add the following code into it: 

<?
include 'db-config.php';

if(!isset($_POST['submit']))
{

	setcookie($_COOKIE['app_login'], "", time() - 3600);
}

$message = '';

if(isset($_POST['submit']))
{
	$inputEmail = $_POST['inputEmail'];
  $inputPassword = $_POST['inputPassword'];

	$pwd = password_hash($inputPassword, PASSWORD_BCRYPT);

  $sql = "SELECT * FROM app_users WHERE email = '$inputEmail'";
	$result = mysqli_query($mysqli, $sql);

  if(mysqli_num_rows($result) &gt; 0) {
    while($row = mysqli_fetch_assoc($result)){
      $userpwd = $row['password'];
    }

    if(password_verify($inputPassword, $pwd)){

      $note = "Welcome";
      $cookie_name = "app_login";
      $cookie_value = $inputEmail;

      if(!isset($_POST['remember'])){

        session_start();

        $_SESSION["name"] = $cookie_name;
        $_SESSION["cookie_value"] = $cookie_value;

      header('Location: userpanel.php');

      } else {

      setcookie($cookie_name, $cookie_value, time() + (86400 * 365), "/");
      header('Location: userpanel.php');

    }
    } else {
      echo "Error";
    }

}
}

?&gt;
<!doctype html&gt;
<html lang="en"&gt;
  <head&gt;
    <meta charset="utf-8"&gt;
    <meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    <meta name="description" content=""&gt;
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"&gt;
    <meta name="generator" content="Hugo 0.79.0"&gt;
    <title&gt;Hypermind</title&gt;
    <!-- Bootstrap core CSS --&gt;
    <link href="https://assets.hypermind.xyz/bootstrap/assets/dist/css/bootstrap.min.css" rel="stylesheet"&gt;

    <style&gt;
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }
    </style&gt;


    <!-- Custom styles for this template --&gt;
    <link href="https://assets.hypermind.xyz/bootstrap/css/signin.css" rel="stylesheet"&gt;
  </head&gt;
  <body class="text-center"&gt;

<main class="form-signin"&gt;
  <form name="register" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?&gt;"&gt;
    <img class="mb-4" src="http://assets.hypermind.xyz/bootstrap/assets/brand/hypermind-logo.svg" alt="" width="100" height="100"&gt;
    <h1 class="h3 mb-3 fw-normal"&gt;Login</h1&gt;

    <label for="inputEmail" class="visually-hidden"&gt;Email address</label&gt;
    <input type="email" id="inputEmail" name="inputEmail" class="form-control" placeholder="Email address" required&gt;

    <label for="inputPassword" class="visually-hidden"&gt;Password</label&gt;
    <input type="password" id="inputPassword" name="inputPassword" class="form-control" placeholder="Password" required&gt;

    <div class="checkbox mb-3"&gt;
      <label&gt;
        <input type="checkbox" name="remember" value="remember-me"&gt; Remember me
      </label&gt;
    </div&gt;

    <button class="w-100 btn btn-lg btn-primary" name="submit" type="submit"&gt;Login</button&gt;
    <p class="mt-5 mb-3 text-muted"&gt;© 2021</p&gt;
  </form&gt;
</main&gt;



  </body&gt;
</html&gt;

You should have a page that looks like this: 

Let’s break down this script in more detail. 

We’re using another PHP_SELF form action to listen out for POST data, which then invokes a query to check the email address and password against the database for a positive match. 

If you remember, our passwords are stored hashed. To check the validity, we’re using the password_verify() function native to PHP. 

If there is a match and the password is correct, we’ll check if the user has confirmed to keep themselves logged in to the platform and if so, set a cookie or create a temporary session and forward them to the admin panel. 


Part 4 – Admin Panel & Logout

Admin Panel

This part is discretionary depending on where you want to direct users once they login.  

Because this is a restricted panel available only to authorised and logged-in users, we do a quick check to see if the Session/ Cookie variable we set exists, and if it does we’ll allow the user to see the page + get their personal data from the database using a Select Query. 

Create a new file called userpanel.php where users will be directed when they login. Copy and paste the following code: 

<?php
session_start();

if(isset($_COOKIE['app_login'])) {

   echo "hello cookie ".$_COOKIE['app_login'];

} else if(isset($_SESSION["cookie_value"])) {

 echo "hello session ".$_SESSION["cookie_value"];

}
?&gt;

When users successfully login, they’ll see their unique user details. Our script is checking to see if there is a temporary session or more long term cookie set in the browser when the user logged in to retrieve the users’ details. Change this script as needed.

Logout

To logout, we need to terminate the session and unset the cookie (if one was set). 

Create a file called logout.php and add the following code: 

<?php
session_start();

$_SESSION = array();

session_destroy();
setcookie($_COOKIE['app_login'], "", time() - 3600);	


// Redirect to login page
header("location: login.php");
exit;
?&gt;

Summary

If you found this article useful, let us know in the comments below and follow us on our social channels. 

For the complete source code – take a look through the downloadable files here.