Home arrow JavaScript arrow Page 2 - Building a CHAP Login System: An Object-Oriented Approach
JAVASCRIPT

Building a CHAP Login System: An Object-Oriented Approach


Welcome to the last part of the series “Building a CHAP login system.” In three parts, this tutorial provides the basics for building secure login forms, by utilizing the Challenge Handshake Authentication Protocol (known popularly as CHAP). The programming foundation of the system resides primarily on the implementation of the cryptographic MD5 hashing algorithm in JavaScript for sending out encrypted data to the server, which in turn authenticates the client.

Author Info:
By: Alejandro Gervasio
Rating: 5 stars5 stars5 stars5 stars5 stars / 30
September 12, 2005
TABLE OF CONTENTS:
  1. · Building a CHAP Login System: An Object-Oriented Approach
  2. · Using a procedural script: a quick overview of the previous login system
  3. · Taking the object-oriented approach: using a session handling class
  4. · Putting the pieces together: integrating the “ChallengeGenerator” class

print this article
SEARCH DEVARTICLES

Building a CHAP Login System: An Object-Oriented Approach - Using a procedural script: a quick overview of the previous login system
(Page 2 of 4 )

Before you look at the approach you can take to building a PHP session management class, the first thing that I’ll do is show the procedural script that implements the CHAP login system. Of course, both client and server processing will be covered, which means providing the code for the JavaScript program along with the PHP authentication script.

Let’s begin listing the code for a sample “login.php” file, which implements the CHAP approach:

<?php
/*
 * Begin of server-side processing
 */
function getRandomString($length=40){
  if(!is_int($length)||$length<1){
    trigger_error('Invalid length for random string');
    exit();
  }
  $chars=
"abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  $randstring='';
  $maxvalue=strlen($chars)-1;
  for($i=0;$i<$length;$i++){
    $randstring.=substr($chars,rand(0,$maxvalue),1);
  }
  return $randstring;
}
function setChallengeVar($name='challenge'){
  if(!is_string($name)||!$name){
    trigger_error('Invalid variable name');
    exit();
  }
  session_start();
  // register session variable
  $_SESSION[$name]=getRandomString();
}
function getChallengeVar($name='challenge'){
  if(!$_SESSION[$name]){
    trigger_error('Invalid variable name');
    exit();
  }
  return $_SESSION[$name];
}
setChallengeVar();
/*
 * End of server-side processing
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>CHAP LOGIN SYSTEM EXAMPLE</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script language="javascript" src="md5.js">
/*
 * include MD5 JavaScript library
 */
<script language="javascript">
/*
 * validate form fields &
 * implement the Challenge Handshaking Authentication Protocol
 */
function doCHAP(){
  valid=true;
  // get 'userid' field
  var usrid=document.getElementById('userid');
  if(!usrid){return};
  if(!usrid.value){showError(usrid,'Enter your ID')};
  // get 'password' field
  var psw=document.getElementById('passwd');
  if(!psw){return};
  if(!psw.value){showError(psw,'Enter your password')};
  // get 'challenge' field
  var chlng=document.getElementById('challenge');
  if(!chlng){return};
  // make MD5 hash of password and concatenate challenge value
  // next calculate MD5 hash of combined values
  chlng.value=MD5(MD5(psw.value)+'<?php echo getChallengeVar()?>');
  // clear password field
  psw.value='';
  return valid;
}
/*
 * display error messages
 */
function showError(obj,message){
  if(!obj.errorNode){
    obj.onchange=hideError;
    var p=document.createElement('p');
    p.appendChild(document.createTextNode(message));
    obj.parentNode.appendChild(p);
   obj.errorNode=p;
 }
  valid=false;
  return
}
/*
 * hide error messages
 */
function hideError(){
  this.parentNode.removeChild(this.errorNode);
  this.errorNode=null;
  this.onchange=null;
}
/*
 * execute 'doCHAP()' function when page is loaded
 */
window.onload=function(){
  var W3CDOM=document.getElementById&&document.
getElementsByTagName&&document.createElement;
  // check if browser is W3CDOM compatible
  if(W3CDOM){
    document.getElementsByTagName('form')[0].
    onsubmit=function(){
      return doCHAP();
    }
  }
}
</script>
</head>
<body>
<!-- login form -->
<form method="post" action="processlogin.php">
User ID <input type="text" name="userid" id="userid"/><br />
Password <input type="password" name="passwd" id="passwd"/><br />
<input type="hidden" name="challenge" id="challenge" />
<input type="submit" name="login" value="Log In" />
</form>
</body>
</html>

By this point, the code included in the above file should be very familiar to you, so for the sake of completeness I’ll only refer to it by dissecting the portions of code that delimit server and client processing respectively. Of course, the package of PHP functions comprising “getRandomString()”, “setChallengeVar()” and “getChallengeVar()” constitutes the core engine for getting a random string, as well as setting and obtaining challenge session variables.

On the client side, the “md5.js” file incorporates the MD5 JavaScript library, which is used to calculate MD5 hashes on user data. By complementing the power of the library, the set of functions “doCHAP()”, “showError()” and “hideError()” applies the CHAP method on the login form by encrypting the password along with the challenge string, so sensitive data is never passed to the server as plain text.

Now, let’s take a look at the client authenticating script, which is included in the “processlogin.php” file:

// connect to MySQL
if(!$db=mysql_connect('host','user','password')){
  trigger_error('Error connecting to the server '.mysql_error());
  exit();
}
// select database
if(!mysql_select_db('database',$db)){
 trigger_error('Error selecting database '.mysql_error());
 exit();
}
// run query
$sql="SELECT userid,password FROM users WHERE userid='".$_POST['userid']."'";
if(!$result=mysql_query($sql,$db)){
  trigger_error('Error running query '.$sql.mysql_error());
  exit();
}
// check if user ID is valid
if(mysql_num_rows($result)<1){
  trigger_error('User not found into database');
  exit();
}
// get user data
if(!$row=mysql_fetch_assoc($result)){
  trigger_error('Error retrieving user data');
  exit();
}
session_start();
$challenge=$_SESSION['challenge'];
// check to see if user credentials are valid
if(md5($row['password'].$challenge)==$_POST['challenge']&&$row
['userid']==$_POST['userid']){
  echo '<html><head><title>Login Successful</title><h1>Thank you
for logging in!</h1></body></html>';
}
else{
  echo '<html><head><title>Access denied!</title><body><h1>Access
denied!</h1></body></html>';
}

First, the above script connects to MySQL and runs a query to get the password and user ID that matches the ID passed through the login form. Then, once these values are obtained, the script calculates the same MD5 checksum of the hashed password and the challenge string combined, for comparison with the values transmitted by the client. If a match is found, the client has logged in successfully. Otherwise, the login process simply fails.

Now that you’ve seen an example of how a procedural method can be used to implement CHAP login systems, the next step will consist of modifying the pertinent files to work with a PHP session handling class. Therefore, keep on reading to find out how this is done.


blog comments powered by Disqus
JAVASCRIPT ARTICLES

- Project Nashorn to Make Java, JavaScript Wor...
- JavaScript Virus Attacks Tumblr Blogs
- Google Releases Stable Dart Version, JavaScr...
- Khan Academy Unveils New JavaScript Learning...
- Accessing Nitro? There`s an App for That
- JQuery 2.0 Leaving Older IE Versions Behind
- Fastest JavaScript Engine Might Surprise You
- Microsoft Adjusting Chakra for IE 10
- Brendan Eich: We Don`t Need Google Native Cl...
- An Overview of JavaScript Statements
- An Overview of JavaScript Operators
- Overview of JavaScript Variables
- More of the Top jQuery Social Plugins
- The Top jQuery Social Plugins
- More of the Top jQuery Slider Plugins

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2018 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials