Showing posts with label Secure login using PHP. Show all posts
Showing posts with label Secure login using PHP. Show all posts

Thursday, 17 July 2014

Tagged under: , , , ,

Forgot Password Functionality in PHP


When you implement a Login functionality, one thing that becomes an obvious inclusion is the 'Forgot Password' functionality. There are several ways to implement the forgot password functionality, some of which may be:


  • Ask the security Question
  • Send a new password to the registered mail, etc etc
But the most popular one is
  • Send an encoded, one time password reset link to the registered mail id
We would be discussing on this, i.e. the password reset link functionality implementation in this tutorial.

Before we get on with the actual coding, we need to create a proper database schema:
In the Table where you store the login credentials, add another column 'forgotpassword', which will store the encoded random string that you would be sending to the registered mail id.

Now comes the code...

Step 1: Ask for the email id with which the user is registered

<?php

$db = mysql_connect($dbhost, $dbuser, $dbpassword);
mysql_select_db($dbdatabase, $db);

if(isset($_POST['submit'])) {
$selectuser="Select * from USERTABLE where emailid='".addslashes($_POST['email'])."'";
$result = mysql_query($selectuser);
$numrows = mysql_num_rows($result);
if($numrows == 1) {
 $row = mysql_fetch_assoc($result);
 $validusername=$result['username'];
 for($i = 0; $i < 16; $i++) {
  $randomstring .= chr(mt_rand(1,126));
 }
 $verifyurl = "resetpwd.php";
 $verifystring = urlencode($randomstring);
 $verifyemail = urlencode($_POST['email']);
 
 $updateuser="Update USERTABLE SET forgotpassword='".addslashes($randomstring)."' WHERE emailid='".addslashes($_POST['email'])."'";
 mysql_query($updateuser);
 
 $mail_body=<<<_MAIL_
Hi,
A request has been made to reset the password for your account.
Please click on the following link to go to the password reset page:
$verifyurl?email=$verifyemail&verify=$verifystring
_MAIL_;
 
 require("class.phpmailer.php");
 $mailer = new PHPMailer();
 $mailer->IsSMTP();
 $mailer->Host = ""; //Add smtp details
 $mailer->SMTPAuth = TRUE;
 $mailer->Username = "";  // Change this to your gmail adress
 $mailer->Password = "";  // Change this to your gmail password
 $mailer->From = "";  // This HAVE TO be your gmail adress
 $mailer->FromName = ""; // This is the from name in the email, you can put anything you like here
 $mailer->Body = $mail_body;
 $mailer->Subject = "User Verification";
 $mailer->AddAddress($_POST['email']);  // This is where you put the email adress of the person you want to mail
 if(!$mailer->Send()){
  echo "Message was not sent<br/ >";
  echo "Mailer Error: " . $mailer->ErrorInfo;
 }
 else{
  echo "<center>A link has been
emailed to the address you entered below.
Please follow the link in the email to reset the passwod for 
your account.</center><br>";
 }
}
else{
 echo "We could not find any registered user with the email id as ".addslashes($_POST['email'])."<br>
 Please Enter the correct mail id & try again";
}
}
else{
?>

<div id="content">
<form action="forgotpwd.php" method="post">
<table>
<tr>
<td>Enter the Mail Id you registered with</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<tr>
<td></td>
<td><input type="submit" name="submit" value="Submit"></td>
</tr>
</table>
</form>
</div>
<?php
}
?>


In the above snippet of code, We ask the user to enter the mail id he/she registered with. Once the user submits the form, you first check if the email id is present in the database, if not, you notify the user accordingly.
Once you find the email id in the database, the next step is to create a random string, encode it and append it to the password reset page url. Encoding of a string can be done using urlencode() method in PHP.
We also store the encoded randomly generated string to the database. Next, encode the mail id of the user and append it too to the url. The next part is where we send this url to the registered mail id. For this, I have used PHP Mailer.
To know more about PHP Mailer as to how it works, refer to my tutorial on this: Sending Email using PHP

Step 2: Check the encoded url when the user clicks it from his mail

<?php

$verify = addslashes(urldecode($_GET['verify']));
$verifymail = urldecode($_GET['email']);

if (isset($_POST['confirmpwdreset'])) {
 $resetpwd="Update USERTABLE SET password='". md5($_POST['newpwd'])."' WHERE emailid='".$verifymail."'"; 
 if(mysql_query($resetpwd))
 {
  $removeverifystring="Update USERTABLE SET forgotpwd='' WHERE emailid='".$verifymail."'";
  mysql_query($removeverifystring);
 }
 echo "<b>Your Password has been reset successfully.Login with your new password</b>";
}
else{
if($verify!=''){
$sql = "SELECT * FROM USERTABLE WHERE forgotpwd= '" . $verify . "' AND emailid = '" .$verifymail . "';";
$result = mysql_query($sql);
$numrows = mysql_num_rows($result);
if($numrows == 1) {
$row = mysql_fetch_assoc($result);
echo "<br><h3>Hi </h3><br>";
echo "You can now reset your password<br><br>";
?>
<form name="reset" action="resetpwd.php?emailid=<?php echo $_GET['emailid'];?>&verify=<?php echo $_GET['verify'];?>" method="post">
<table>
<tr>
<td>New password: </td><td><input type="password" name="newpwd"></td>
</tr>
<tr>
<td>Confirm password: </td><td><input type="password" name="confirmpwd"></td>
</tr>
<tr>
<td></td><td><input type="submit" name="confirmpwdreset" value="Confirm"></td>
</tr>
</table>
<?php
} 

else {
echo "The link is either invalid or has expired";
}
}
else echo "The link is either invalid or has expired";
}
?>


Once the user clicks the url in the mail, we decode the random string and the email-id in the url. For decoding, we can use the urldecode() method in PHP. Next, all we have to do is to check the database for the combination of the random string and the mail-id. Once we find that combo, we ask the user to enter the new password, which on submission is updated in the database. As we update the database with the new password value, we reset the value of the corresponding 'forgotpassword' field to '' so that the same random string cannot be reused, thus ensuring one time usability of password reset url

Thats it!! We now have a full fledged 'Forgot Password' functionality to make life easy for the users.

Saturday, 14 July 2012

Tagged under: , , ,

Secure Login Code using PHP and MySQL / Preventing SQL Injection using PHP

Many Web pages accept parameters from web users and generate SQL queries to the database. SQL Injection is a trick to inject SQL script/command as an input through the web front end.

Your application may be susceptible to SQL Injection attacks when you incorporate invalidated user input into the database queries. Particularly susceptible is a code that constructs dynamic SQL statements with unfiltered user input.



Consider the following example code:
Sql DataAdapter myCommand = new SqlDataAdapter(
"Select * from Users
Where UserName = ' "+txtuid.Text+" ", conn);

Attackers can inject SQL by terminating the intended SQL statement with the single quote character  followed by a semicolon character to begin a new command and then executing the command to their choice. Consider the following character string entered into the .txtuid field.
' OR 1=1
This results in the following statement to be submitted to the database for execution:
SELECT * FROM Users WHERE UserName = ' ' OR 1 = 1;

Because 1=1 is always true, the attacker retrieves very row of data from the user table.

Now, to prevent such an attack, a secure login technique is required. Here, in this article, we discuss the coding of a secure login script using PHP and MySQL.


Step I: Create a database and a table 'members' in it:

CREATE TABLE `members` (
  `username` varchar(20),
  `password` varchar(128)
)



Step II: Create a Login Form:

<form action="process_login.php" method="post">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="Login" />
</form>


Connect to MySQL Server:

$host = 'localhost'; // Host name Normally 'LocalHost'
$user = 'root'; // MySQL login username
$pass = ''; // MySQL login password
$database = 'test'; // Database name
$table = 'members'; // Members name
 
mysql_connect($host, $user, $pass);
mysql_select_db($database);


Step III: Now, you need to provide mechanism to avoid SQL Injection. For this, escape special characters like ", ', \

We can escape special characters (prepend backslash) using mysql_real_escape_string or addslashes functions. In most cases PHP will this do automatically for you. But PHP will do so only if the magic_quotes_gpc setting is set to On in the php.ini file.
If the setting is off, we use mysql_real_escape_string function to escape special characters. If you are using PHP version less that 4.3.0, you can use the addslashes function instead.

name = mysql_real_escape_string($_POST['username']);
$password = md5($_POST['password']);
 
$result = mysql_query("SELECT * FROM $table WHERE username = '$username' AND password = '$password'
");


Here, we use the MD5(Message Digest 5) Algorithm, that generates the message digest for the password. So, while writing the script for registration page, care must be taken that the md5 of the password entered by the user must be stored in the database, instead of the actual text password. In a real world situation, do not use MD5, as it is no longer considered secure. Use some other secure hashing algorithm.

Validating the login:

if(mysql_num_rows($result))
{
  // Login
  session_start();
  $_SESSION['username'] = htmlspecialchars($username); 
}
else
{
  // Invalid username/password
  echo '<p><strong>Error:</strong> Invalid username or password.</p>';
}
 
// Redirect
header('Location: http://www.example.com/loggedin.php');
exit;


You are done!! This code will help prevent the SQL injection problem. However, it must be noted that no script is 100% secure. So, it is advisable to provide multilevel security process, which make the login more secure.