Friday, November 2, 2018

OOP PHP Login Tutorial




  What is a PHP Secure Login System with Registration?



Many applications need to register and authenticate users. Some users have developed their own packages for this purpose, others have used existing packages. The problem is that some of those packages are vulnerable to different types of exploits because their developers were not aware of the security issues they may incur.

A secure login and registration system should at avoid SQL injections, using for instance database prepared statements with PDO, use a strong password hashing method to minimize the chance that if the site leaks user accounts it is impossible or at least very hard to discover the users' passwords, and limit the number of attempts that a user may fail a password to avoid brute force attacks.

This tutorial covers the implementation of a login and registration system using the PHP Secure Login and Registration package. In this tutorial I will show different aspects of the class features, so you can see  the different ways of how to use this package.

I will use Bootstrap and jQuery for the user interface and submitting forms using AJAX requests or regular form page submission. Don't be worried if you do not use AJAX everywhere. The tutorial is presented this way on propose so more people can take advantage of the knowledge shared here.

What this Secure PHP Login System Class can do?

This class provides a simple way to register new users. It supports a secure PHP login process after activation with the login verification code sent to their email address. It uses jQuery to submit forms using AJAX request to the scripts that act like a REST API, but can also be used directly with PHP scripts that serve the login pages.

This class also provides a solution in PHP to block user after a number of login attempts, I mean it lets  you specify a number of wrong attempts that it allows before blocking the account. It also lets users logout, change their password and have different permissions depending on the user role.

As many of us are using PHP 7, or at least PHP 5.5, obviously it is an OOP login system. Since usually our applications support multi-user login, I mean multiple users accessing at the same time, it makes perfect sense to store user records in a database.

It supports PDO, so you can use it to store user database records using MySQL, PostgreSQL, SQLite and others. The example included here will explain how to use it with MySQL. It could use MySQLi instead of PDO but it will be more useful if you can reuse this code with other types of database.

Since we can use PDO also with SQLite, we can use to implement a PHP login without database , I mean a real database server, as SQLite stores the database in local files.

This class could also be extend to implement a social login system using OAuth to perform login with Facebook, Yahoo, Google, YouTube, Gmail, Microsoft, LinkedIn, GitHub, BitBucket, Instagram, Tumblr, deviantart, WordPress, ODesk and many others.

But for that you will need to use also other classes to perform login with OAuth or even LDAP for login. A good idea for future improvements is to also to support SMS login, I mean using a method to send a code via SMS to let the user prove he owns a given account, or even check the Mac address to restrict the access to users in a local network. But for now let us keep it simple.

The Start PHP Secure Login Page Script :

We will need a start page where visitors can register or login. I am using Bootstrap to construct a simple page on which we have two tabs, one for login and the other for registration.

When a visitor registers, usually we will need verify that he owns the email he entered. So he will also need a place to send the verification code to activate his new account. I am putting that also in the login tab.

<?php
    require_once '../class/user.php';
    require_once 'config.php';

    $user->indexHead();
    $user->indexTop();
    $user->loginForm();
    $user->activationForm();
    $user->indexMiddle();
    $user->registerForm();
    $user->indexFooter();
?>

This class uses template scripts that you may find in the inc directory. If you look at the template files, you can see we are using jQuery and Bootstrap, as well use two custom files, one for CSS and the other for JS.
In the body I added three form areas auto-generated by the class: two in the login section and one in the registration section. You can also see that I separated them in tabs.
You can find a lot of tutorials about Bootstrap on how to work with tabs. The first form will be used for login, the next one for account verification, and the last one for registration.

JavaScript and AJAX Form Submission :

In the main.js file I am using jQuery and AJAX requests. This is important if we want to use the REST API method. This is very useful if we want to separate the frontend from the backend.

$(function() {

    $('#login-form-link').click(function(e) {
        $("#login-form").delay(100).fadeIn(100);
        $("#register-form").fadeOut(100);
        $('#register-form-link').removeClass('active');
        $(this).addClass('active');
        e.preventDefault();
    });

    $('#register-form-link').click(function(e) {
        $("#register-form").delay(100).fadeIn(100);
        $("#login-form").fadeOut(100);
        $('#login-form-link').removeClass('active');
        $(this).addClass('active');
        e.preventDefault();
    });
});
function validateEmail($email) {
    var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,})?$/;
    return emailReg.test( $email );
}

The Login Process Script

For login the script gets the posted data and passes it to the login method of the class. If the login succeeds, it will assign the user data to session login variables and returns nothing as the result. If there is an error it will print it.

Do not forget we are calling this script via AJAX, so everything outputted by the script will be delivered as a result of the AJAX call in JavaScript.

<?php
    require_once '../class/user.php';
    require_once 'config.php';

    $email = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_EMAIL);
    $password = filter_input(INPUT_POST, 'password', FILTER_DEFAULT);

    if( $user->login( $email, $password) ) {
        die;
    } else {
        $user->printMsg();
        die;
    }

The Registration Process Script

As in login process, this is also a very simple code sample, where I use the registration method in the user class. If a registration passes then we will print a confirmation message or an error message instead.

<?php
    require_once '../class/user.php';
    require_once 'config.php';

    $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
    $fname = filter_input(INPUT_POST, 'fname', FILTER_SANITIZE_STRING);
    $lname = filter_input(INPUT_POST, 'lname', FILTER_SANITIZE_STRING);
    $pass = filter_input(INPUT_POST, 'password', FILTER_DEFAULT);

    if($user->registration($email, $fname, $lname, $pass)) {
        print 'A confirmation mail has been sent, please confirm your account registration!';
        die;
    } else {
        $user->printMsg();
        die;
    }

The Activation Process Script

After registration the user needs to activate his account. So we are using here the emailActivation method. Again a strait forward code sample that outputs an error message if the activation fails, or nothing if it passes.

<?php
    require_once '../class/user.php';
    require_once 'config.php';

    $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
    $code = filter_input(INPUT_POST, 'code', FILTER_DEFAULT);
    
    if($user->emailActivation( $email, $code)) {
        die;
    } else {
        $user->printMsg();
        die;
    }

The Logout Process Script

For the logout process I use logout method in the user class. After logout process is conclude we simply redirect the user to index.php. The logout process is not started via AJAX in this example. If we call it via AJAX then the redirect is done by JavaScript code, and so not in PHP.

<?php
    require_once '../user.php';
    require_once 'config.php';

    $user->logout();

    header('location: index.php');
?>

The Configuration Script File

An important file I need to describe is the config.php. It is necessary to specify the database connection details and to initiate the session. This login and registration class will not work without sessions. It also will creates the user class object so we can use it in every other file. As you saw before we included this script every time after the class itself.

Also we need to specify the files we are using in the HTML generation functions. In this case user.php, login.php, activate.php and register.php. You can customize these files.

<?php
    session_start();
    define('conString', 'mysql:host=localhost;dbname=login');
    define('dbUser', 'root');
    define('dbPass', 'root');

    define('userfile', 'user.php');
    define('loginfile', 'login.php');
    define('activatefile', 'activate.php');
    define('registerfile', 'register.php');

    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);

    $user = new User();
    $user->dbConnect(conString, dbUser, dbPass);
?>

The Logged User Section Script

After logging in, the users have a section on the site where they can see what non-logged visitors can see because it is only for registered users.

For this tutorial I created an example of what could be that section in the file user.php script. You may notice two cases. If a normal user is logged in it will show him only his information. But if the user is an administrator, in this case his role ID is 2 (you can change this to any ID number) then he sees a list off all the users in the system.

<?php
   require_once '../class/user.php';
   require_once 'config.php';

   if(IsSet($_SESSION['user']['id']) {
       $user->userPage();
   } else {
      header('Location: index.php');
   }
?>



0 comments:

Post a Comment