In our previous post, explains you the login system using PHP with PDO connection. Here is an extra feature that can be added to login system for an extra layer of security. It is 2 factor authentication using Google Authenticator App for Android/iPhone. Your account could be at risk of having your password stolen. 2 step verification can protect from misuse of your account if someone have your password, because logging into your account always require a security code(this verification code is uniquely designed for your account, if you opt for verification code, an unique code is sent to your mobile for every 30-60 seconds) in the second step after you enter your password.
Download Script Live Demo
With 2 step verification, we can protect our account with both password and mobile. Add this 2 factor authentication to make your account more stronger.
Get Google Authenticator on your phone
Download and install Google Authenticator application on your mobile device, use the following icons. You need this for 2 step user authentication, please watch the following demo video.
Demo Video
Users Table
User table contains all the users registration details, here you have to store user details with unique Google authentication code.
CREATE TABLE `users` (
`uid` int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(25) NOT NULL UNIQUE,
`password` varchar(200) NOT NULL ,
`email` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`profile_pic` varchar(200) NOT NULL,
`google_auth_code` varchar(16) NOT NULL /* 16 digit code */
);
`uid` int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(25) NOT NULL UNIQUE,
`password` varchar(200) NOT NULL ,
`email` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`profile_pic` varchar(200) NOT NULL,
`google_auth_code` varchar(16) NOT NULL /* 16 digit code */
);
Enable PDO extension for PHP, find this in php.ini configuration file.
The tutorial contains two folders called googleLib and class with PHP files.
googleLib
-- GoogleAuthenticator.php // Google Authentication Library
class
-- userClass.php
config.php // Database configration file
index.php // Login and Signup page
device_confimation.php // Device confirmation page.
home.php // User welcome page
logout.php // Logout Page
sessions.php // User session
-- GoogleAuthenticator.php // Google Authentication Library
class
-- userClass.php
config.php // Database configration file
index.php // Login and Signup page
device_confimation.php // Device confirmation page.
home.php // User welcome page
logout.php // Logout Page
sessions.php // User session
config.php
Database connection configuration file, here you have to modify username, password and database details. If you are using other database modify PDO() driver connection value.
<?php
session_start();
/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_PASSWORD', 'password');
define('DB_DATABASE', 'databasename');
define("BASE_URL", "http://localhost/PHPLoginHash/"); // Eg. http://yourwebsite.com
function getDB()
{
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?>
session_start();
/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_PASSWORD', 'password');
define('DB_DATABASE', 'databasename');
define("BASE_URL", "http://localhost/PHPLoginHash/"); // Eg. http://yourwebsite.com
function getDB()
{
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?>
HTML Login Signup Form
This post will help you design HTML login and registration forms PHP Login System with PDO Connection.
userClass.php
This class contains there methods userLogin, userRegistion and userDetails.
<?php
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password");
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
$_SESSION['google_auth_code']=$google_auth_code; //Stroing Google authentication code
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Registration */
public function userRegistration($username,$password,$email,$name,$secret)
{
try{
$db = getDB();
$st = $db->prepare("SELECT uid FROM users WHERE username=:username OR email=:email");
$st->bindParam("username", $username,PDO::PARAM_STR);
$st->bindParam("email", $email,PDO::PARAM_STR);
$st->execute();
$count=$st->rowCount();
if($count<1)
{
$stmt = $db->prepare("INSERT INTO users(username,password,email,name,google_auth_code) VALUES (:username,:hash_password,:email,:name,:google_auth_code)");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$hash_password= hash('sha256', $password); //Password encryption
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("name", $name,PDO::PARAM_STR) ;
$stmt->bindParam("google_auth_code", $secret,PDO::PARAM_STR) ;
$stmt->execute();
$uid=$db->lastInsertId(); // Last inserted row id
$db = null;
$_SESSION['uid']=$uid;
return true;
}
else
{
$db = null;
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name,google_auth_code FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password");
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
$_SESSION['google_auth_code']=$google_auth_code; //Stroing Google authentication code
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Registration */
public function userRegistration($username,$password,$email,$name,$secret)
{
try{
$db = getDB();
$st = $db->prepare("SELECT uid FROM users WHERE username=:username OR email=:email");
$st->bindParam("username", $username,PDO::PARAM_STR);
$st->bindParam("email", $email,PDO::PARAM_STR);
$st->execute();
$count=$st->rowCount();
if($count<1)
{
$stmt = $db->prepare("INSERT INTO users(username,password,email,name,google_auth_code) VALUES (:username,:hash_password,:email,:name,:google_auth_code)");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$hash_password= hash('sha256', $password); //Password encryption
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("name", $name,PDO::PARAM_STR) ;
$stmt->bindParam("google_auth_code", $secret,PDO::PARAM_STR) ;
$stmt->execute();
$uid=$db->lastInsertId(); // Last inserted row id
$db = null;
$_SESSION['uid']=$uid;
return true;
}
else
{
$db = null;
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name,google_auth_code FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>
index.php
Contains PHP and HTML code, works base on user form submit..
<?php
include("config.php");
if(!empty($_SESSION['uid']))
{
header("Location: device_confirmations.php");
}
include('class/userClass.php');
$userClass = new userClass();
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$secret = $ga->createSecret(); //This function will create unique 16 digit secret key
$errorMsgReg='';
$errorMsgLogin='';
/* Login Form */
if (!empty($_POST['loginSubmit']))
{
$usernameEmail=$_POST['usernameEmail'];
$password=$_POST['password'];
if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
{
$uid=$userClass->userLogin($usernameEmail,$password);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgLogin="Please check login details.";
}
}
}
/* Signup Form */
if (!empty($_POST['signupSubmit']))
{
$username=$_POST['usernameReg'];
$email=$_POST['emailReg'];
$password=$_POST['passwordReg'];
$name=$_POST['nameReg'];
/* Regular expression check */
$username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
$email_check = preg_match('~^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
$password_check = preg_match('~^[A-Za-z0-9!@#$%^&*()_]{6,20}$~i', $password);
if($username_check && $email_check && $password_check && strlen(trim($name))>0)
{
$uid=$userClass->userRegistration($username,$password,$email,$name);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgReg="Username or Email already exists.";
}
}
}
?>
//HTML Code
....Login Form HTML Code....
....Signup Form HTML Code...
include("config.php");
if(!empty($_SESSION['uid']))
{
header("Location: device_confirmations.php");
}
include('class/userClass.php');
$userClass = new userClass();
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$secret = $ga->createSecret(); //This function will create unique 16 digit secret key
$errorMsgReg='';
$errorMsgLogin='';
/* Login Form */
if (!empty($_POST['loginSubmit']))
{
$usernameEmail=$_POST['usernameEmail'];
$password=$_POST['password'];
if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
{
$uid=$userClass->userLogin($usernameEmail,$password);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgLogin="Please check login details.";
}
}
}
/* Signup Form */
if (!empty($_POST['signupSubmit']))
{
$username=$_POST['usernameReg'];
$email=$_POST['emailReg'];
$password=$_POST['passwordReg'];
$name=$_POST['nameReg'];
/* Regular expression check */
$username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
$email_check = preg_match('~^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
$password_check = preg_match('~^[A-Za-z0-9!@#$%^&*()_]{6,20}$~i', $password);
if($username_check && $email_check && $password_check && strlen(trim($name))>0)
{
$uid=$userClass->userRegistration($username,$password,$email,$name);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php
}
else
{
$errorMsgReg="Username or Email already exists.";
}
}
}
?>
//HTML Code
....Login Form HTML Code....
....Signup Form HTML Code...
Note: You have to include JavaScript validations for better user experience.
device_confirmation.php
<?php
include('config.php');
if(empty($_SESSION['uid']))
{
header("Location: index.php");
}
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);
$secret=$userDetails->google_auth_code;
$email=$userDetails->email;
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$qrCodeUrl = $ga->getQRCodeGoogleUrl($email, $secret,'Your Application Name');
?>
//HTML Code
Enter the verification code generated by Google Authenticator app on your phone.
<div id="img">
<img src='<?php echo $qrCodeUrl; ?>' />
</div>
<form method="post" action="home.php">
<label>Enter Google Authenticator Code</label>
<input type="text" name="code" />
<input type="submit" class="button"/>
</form>
include('config.php');
if(empty($_SESSION['uid']))
{
header("Location: index.php");
}
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);
$secret=$userDetails->google_auth_code;
$email=$userDetails->email;
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$qrCodeUrl = $ga->getQRCodeGoogleUrl($email, $secret,'Your Application Name');
?>
//HTML Code
Enter the verification code generated by Google Authenticator app on your phone.
<div id="img">
<img src='<?php echo $qrCodeUrl; ?>' />
</div>
<form method="post" action="home.php">
<label>Enter Google Authenticator Code</label>
<input type="text" name="code" />
<input type="submit" class="button"/>
</form>
home.php
User welcome page, display user details base on user session value.
<?php
include('config.php');
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);
if($_POST['code'])
{
$code=$_POST['code'];
$secret=$userDetails->google_auth_code;
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$checkResult = $ga->verifyCode($secret, $code, 2); // 2 = 2*30sec clock tolerance
if ($checkResult)
{
$_SESSION['googleCode']=$code;
}
else
{
echo 'FAILED';
}
}
include('session.php');
$userDetails=$userClass->userDetails($session_uid);
?>
//HTML Code
<h1>Welcome <?php echo $userDetails->name; ?></h1>
<h2> Email <?php echo $userDetails->email; ?></h2>
<a href="<?php echo BASE_URL; ?>logout.php">Logout</a>
include('config.php');
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);
if($_POST['code'])
{
$code=$_POST['code'];
$secret=$userDetails->google_auth_code;
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$checkResult = $ga->verifyCode($secret, $code, 2); // 2 = 2*30sec clock tolerance
if ($checkResult)
{
$_SESSION['googleCode']=$code;
}
else
{
echo 'FAILED';
}
}
include('session.php');
$userDetails=$userClass->userDetails($session_uid);
?>
//HTML Code
<h1>Welcome <?php echo $userDetails->name; ?></h1>
<h2> Email <?php echo $userDetails->email; ?></h2>
<a href="<?php echo BASE_URL; ?>logout.php">Logout</a>
session.php
his will validate and store the user session value.
<?php
if(!empty($_SESSION['uid']) && !empty($_SESSION['googleCode']))
{
$session_uid=$_SESSION['uid'];
$session_googleCode=$_SESSION['googleCode'];
}
if(empty($session_uid) && empty($session_googleCode))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
if(!empty($_SESSION['uid']) && !empty($_SESSION['googleCode']))
{
$session_uid=$_SESSION['uid'];
$session_googleCode=$_SESSION['googleCode'];
}
if(empty($session_uid) && empty($session_googleCode))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
logout.php
This code will clear the user and Google aunthentication session values.
<?php
include('config.php');
$session_uid='';
$session_googleCode='';
$_SESSION['uid']='';
$_SESSION['googleCode']='';
if(empty($session_uid) && empty($_SESSION['uid']))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
include('config.php');
$session_uid='';
$session_googleCode='';
$_SESSION['uid']='';
$_SESSION['googleCode']='';
if(empty($session_uid) && empty($_SESSION['uid']))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>
ReplyDeleteMostrando traducción para awesome gracias
En su lugar, traducir del aweson gracias
awesome
Thank you
Well,I love Google so definitely will love this! ♥
ReplyDeletesuper cool!!
ReplyDeleteConnection failed: SQLSTATE[28000] [1045] Access denied for user 'a1832414_bali'@'10.1.1.31' (using password: YES)
ReplyDeletePHP Error Message
Fatal error: Call to a member function bindParam() on a non-object in /home/a1832414/public_html/class/userClass.php on line 39
Free Web Hosting
What is this shit???
Man , Download Script , NOT FOUND :(
ReplyDeleteTry again, it is working for me.
DeleteYes unable to download
Deletethanks for great tuturial.I have a question; how we can use this login and signup form with this method for wordpress site?
ReplyDeleteThere is a Google Authenticator plugin for Wordpress.
DeleteHow to using password of google account to login?
ReplyDeleteworking fine for Signup page But not on login page for me any help please?
ReplyDeleteAnyone can authenticate using his phone ? Is it related to user email id ?
ReplyDeleteI have done signup in demo. And try scan with same device which i used while signup then login was successful.
ReplyDeleteBut I used another device to scan QR code then also login successful.
So, how it is secure? If hacker steal my password and try his/her device to scan QR code, then hacker can be able to login.
Please guide me ASAP.
A late response, but i just found the script. I agree on this. The QR code should only be visable on registration so it will be added to your account. On that point your mobile device can generate the 2FA code and you dont need the QR code anymore.
DeleteSo it should only be available on registration not at the login page
when i scan bar code i get the code and when i entered that code after that nothing happens.
ReplyDeletedemo is working fine..
ReplyDeletei downloaded the code and when i scan the bar code i get the security key after entering that security key nothing happens ....?
Try again, it is working for me.
DeleteThere is an error in the sql code. last comma after NULL should be removed (comma cant be at the end of an )
ReplyDelete`google_auth_code` varchar(16) DEFAULT NULL,
i dont see the security in this though. scanning the bar code on creating my account is ok, but why do you display the barcode again after registration and i have a valid account. You should only show the 2FA field where i put in the code generated by my app on my phone
Hi Srini,
ReplyDeleteIt's a good tutorials. I have one question. Can we have a list of 8 digit recovery codes as google gives?
I believe the recovery codes will not be generated by the app or API, however you have to generate it and store in DB against the user email. Later you have to verify with codes stored in the database
DeleteMany thanks in sharing and explaining, works awesome, appreciate...
ReplyDeleteHello SRINIVAS TAMADA,
ReplyDeleteI try your code on my website and it is working fine but did you see one mistake in your code.
When you login and enter google code then you go on home.php page right. Now you try this: Do not logout your home.php and open again index.php on different tab here its goes directly device_confirmations.php page it is good. When you enter any random text or number in textbox or without enter anything in the textbox its directly go to home.php that's not good.
If you have any solution for this please share me
Thanks
index.php should not be openable after login session generated, this is just opposite logic we use to not let people open after login page.
DeleteIt is directly go on home.php page when you do not logout your account and open index.php on second tab
ReplyDeleteYes it works based on the user session
Deleteit's not working for me.. Code and calculatedCode didn't matched in verifyCode function..Any help?
ReplyDeleteShould we use GoogleAutheticator.php from that source :
ReplyDeletehttps://github.com/PHPGangsta/GoogleAuthenticator/blob/master/PHPGangsta/GoogleAuthenticator.php
Because index.php reports :
Fatal error: Uncaught Error: Class 'GoogleAuthenticator' not found in /index.php:11 Stack trace: #0 {main} thrown in /index.php on line 11
Authentication on localhost is successful but on the website the authentication error code
ReplyDeleteDear Admin Please remove comma(,) in lat line of user.sql when download.
ReplyDeleteHow to recover this hash password?
ReplyDelete100% work perfectly.
ReplyDeletejust create database set username,password in config.php also set BASE_URL in config.php and test.
working like magic.
Thanks man you made my day.
Thanks. It's working well in mylocalhost, but on servers it doesn't. I think have to do something for time setup. can you assist me?
ReplyDeletecode is not matching in localhost
ReplyDeleteThe 'users.sql has error(s) when importing into database using phpmysql.
ReplyDeletein the demo url whenever i login QRcode is visible and any one can scan and login if they know my username and password
ReplyDeleteThank you very much....this really helps me.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete
ReplyDeletehello i am getting these errors
Warning: include(class/userClass.php): failed to open stream: No such file or directory in /home/vhosts/onlinestockmanagement.xp3.biz/index.php on line 7
Warning: include(): Failed opening 'class/userClass.php' for inclusion (include_path='.:/opt/remi/php72/root/usr/share/pear:/opt/remi/php72/root/usr/share/php:/usr/share/pear:/usr/share/php') in /home/vhosts/onlinestockmanagement.xp3.biz/index.php on line 7
Fatal error: Uncaught Error: Class 'userClass' not found in /home/vhosts/onlinestockmanagement.xp3.biz/index.php:8 Stack trace: #0 {main} thrown in /home/vhosts/onlinestockmanagement.xp3.biz/index.php on line 8