PHP Authentication Example
In this example we are going to show you how to add an authentication system to your website. Authentication is an integral part of any web app that works with a login and registration system. Web apps like facebook.com, twitter.com and amazon.com use authentication to secure there users.
Authentication is the process of determining whether someone or something is, in fact, who or what is declared to be. When you login into your facebook account, facebook has to be sure it is really you trying to login to your account and not an impostor. The process by which facebook guarantees that you really own the account (and not your evil twin), is authentication. Authentication has to be done correctly.
In this example we will develop a simple login and registration web app that shows the process of authentication in php.
For this example we will use:
- A computer with PHP 5.5 installed
- Mysql server
- notepad++
- Phpmyadmin: This is not compulsory. (All the codes in this example will work correctly even without it). If you want a graphical user interface for manipulating your datbase, then you should install it.
1. Getting Started
If you are developing on your local machine, you can download and install wamp. Wamp installs both php, phpmyadmin and mysql on your local machine. Furthermore, wamp doesn’t require any specific prior knowledge to get it working.
1.1 Initializing the database
This tutorial assumes you have php and mysql running. You should also create a database named authentication.
db.php
<?php $dsn = "mysql:dbname=authentication"; $username = "root"; $password = ""; try{ $conn = new PDO( $dsn, $username, $password ); $conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); } catch(PDOException $pd){ echo $pd->getMessage(); } ?>
This script creates a connection to the database. We are using PDO (Php data objects) to access our database. The connection is stored in the $conn
object and it is made available to manipulate the database.
We create a new PDO object in line 6 and surround it with a try/catch statement, so as to catch any error that might occur while trying to connect to the database.
init.php
<?php require_once("db.php"); try{ $sql="create Table Myuser(id smallint unsigned not null AUTO_INCREMENT PRIMARY KEY, name VARCHAR(265) NOT NULL,email VARCHAR(265) NULL,password VARCHAR(265) NOT NULL)"; $conn->exec($sql); echo "TABLE CREATED"; } catch(PDOException $pd){ echo "Error Creating Table: " . $pd->getMessage(); } $conn=null;//close the database connection ?>
Before you register/login with the index.php script, you should load this script(init.php) into your browser (just once). The script creates a table that is called “Myuser” in the database. In line two we include the “db.php” script to login to the database. In line 5 we create a table in our database by calling the $conn->exec($sql)
method, which takes a string as a parameter (the string holds the sql query).
1.2 Authenticating users
Here comes the interesting part. Let’s take a look at our login and register form.
index.php
<!DOCTYPE html> <html lang=en> <head> <style> html, body{ width:100%; height:100%; margin:0%; font-family:"helvetica","verdana","calibri", "san serif"; overflow:hidden; padding:0%; border:0%; } .a{ width:20%; margin:10px; height:40px; } .a1{ display:inline; width:20%; height:30px; } #sub{ display:inline; } </style> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"/> <title></title> </head> <body> <h1>Login And Registration Form</h1> <div id=cen align=right> <form action="submit.php" method=post> <input type=text class=a placeholder=name name=name required><br> <input type=email class=a placeholder=email name=email required><br> <input type=password class=a placeholder=Password name=password required><br> <input type=submit class=a value=Regster name=register> </form> <div align=right> \ <form action="submit.php" method=post> <input type=email class=a placeholder=email required name=email><br> <input type=password class=a placeholder=password required name=password><br> <input type=submit class=a value=Login id=sub name=login> </form> </div> </div> </body> </html>
This page contains the login and registration form. After a user fills the login or registration form and submit it, our php script “submit.php” is called. We created a class called Database in the database.php script. This class contains the methods that perform authentication.
database.php
<?php require_once("db.php"); class Database{ public function closeDataBase(){ $conn=null; } /* this checks if the user exists @param email is users email @param $conn is the connection object */ public function checkUserExist($email,$conn){ $sql="select count(*) from Myuser where email=:email"; $st=$conn->prepare($sql); $st->bindValue(':email',$email); $st->execute(); $num=$st->fetchColumn(); $st=null; if($num>0) return true; else return false; } /* This method authenticates the user @param email is users email @param password is the submitted password @param $conn is the connection object */ public function authen($email,$password,$conn){ $sql="select password from Myuser where email=:email"; $st=$conn->prepare($sql); $st->bindValue(":email",$email); $res=$st->execute(); $row=$st->fetchAll(); if(password_verify($password,$row[0]['password'])) return true; else return false; } public function register($email,$password,$name,$conn){ $hash=password_hash($password,PASSWORD_DEFAULT);//we hash our password $sql="INSERT INTO Myuser ( email, password,name ) VALUES ( :email, :password ,:name)"; $st=$conn->prepare($sql); $st->bindValue(":email",$email); $st->bindValue(":password",$hash); $st->bindValue(":name",$name); $st->execute(); $st=null; } } ?>
The class database contains four important functions.
closeDataBase():
As the name implies it closes the database. It is wise to close a database connection after you are through with it. To close a database using PDO you need to destroy the PDO object by ensuring that all remaining references to it are deleted—You do this by assigning NULL to the variable that holds the PDO object. If you don’t do this explicitly, PHP will automatically close the connection when your script ends. We close out database by setting the PDO object to null.$conn=null
.
Note: Many web applications will benefit from persistent connection to the database. Persistent connections will not be closed at the end of the script, but are going to be cached and re-used when another script requests a connection using the same credentials. Persistent connections are useful as it help prevent the overhead of establishing a new connection to the database everytime a script needs to talk to the database.checkUserExist($email,$conn)
: As the name implies this method checks if a particular user exists. It checks if the email supplied as a parameter exists in the database. If it exists then this user is already registered otherwise the user is not registered.register($email,$password,$name,$conn)
: This code registers a new user. It saves the users email, password and name in the database.
Note: Never Never Never! save a users password as text in the database, it is wrong. If your database gets compromised, the attacker will get easy access to your users password(The attacker then will gain access to the users account causing varying degrees of damage). Saving a user password as text, makes your web app vulnerable and defeats the need for authentication.
Also never use sha1 and md5 to hash your users password. As computing power has increased the feasibility of breaking the SHA1 and md5 hash has been increased. You should use bcrypt for hashing your password. To use bcrypt for password hashing, in line 45 we call thepassword_hash()
which takes the password to hash as the first parameter and an hashing algorithm as the second parameter. The algorithm we can use arePASSWORD_DEFAULT
andPASSWORD_BCRYPT
. If you are going to use thePASSWORD_DEFAULT
as your hashing algorithm it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).authen()
This authenticates the user when they try to login. Thepassword_verify()
function takes a plain password and the hashed string as its two arguments. It returns true if the hash matches the specified password.
submit.php
<?php require_once("database.php"); $db=new Database(); if(isset($_POST["login"])){ $password=$_POST["password"]; $email=$_POST["email"]; if(!empty($email) && !empty($password)){ if($db->checkUserExist($email,$conn)){//if this user exists if($db->authen($email,$password,$conn)) header("Location:success.html"); ELSE header("Location:error.html"); } else header("Location:error.html"); } $db->closeDataBase(); } else if(isset($_POST["register"])){ $email=$_POST['email']; $name=$_POST['name']; $password=$_POST['password']; if(!empty($email) && !empty($password) && !empty($name)){ $db->register($email,$password,$name,$conn); header("Location:success.html"); } $db->closeDataBase(); } ?>
In line three we instatiate the database class. In line four we check if the user is trying to login. In line eight we check if the user exists and if the user does not exist or authentication fails we redirect him to an error page. If the authentication succeeds we redirect the user to the welcome page.
In line 20 we check if the user is trying to register. If the user is trying to register, in line 25 we call the $db->register();
method to register the user and redirect him to the welcome page
2. Summary
In this example we learnt about authentication in php, what it means and how to do it correct. We have also learnt the common pitfalls when implementing authentication and how to avoid them.