Home arrow JavaScript arrow Page 4 - 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 - Putting the pieces together: integrating the “ChallengeGenerator” class
(Page 4 of 4 )

Definitely, coupling the PHP class to the existing CHAP script is pretty straightforward, since I’ll only replace the pieces of procedural code with the class itself. Considering that the previous login system is quite familiar to you, below is the complete code that implements the system, this time utilizing the “ChallengeGenerator” class that you just saw:

<?php
/*
 * Begin of server-side processing
 */
class ChallengeGenerator{
  // constructor
  function ChallengeGenerator($clearSession=true){
    if($clearSession){
      $this->clearVars();
    }
    session_start();
  }
  // public method clearVars()
  function clearVars(){
    // destroy existing session
    session_start();
    session_unset();
    session_destroy();
  }
  // public method setChallengeVar()
  function setChallengeVar($name='challenge'){
    if(!is_string($name)||!$name){
      trigger_error('Invalid variable name');
      exit();
    }
    // register session variable
    $_SESSION[$name]=$this->getRandomString();
  }
  // public method getSessionVar()
  function getChallengeVar($name){
    if(!$_SESSION[$name]){
      trigger_error('Invalid variable name');
      exit();
    }
    return $_SESSION[$name];
  }
  function deleteChallengeVar($name){
            if(!$_SESSION[$name]){
      trigger_error('Invalid variable name');
      exit();
    }
            unset($_SESSION[$name]);
  }
  // private method "getRandomString()"
  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;
  }
}
// instantiate a ChallengeGenerator object
$chlgen=&new ChallengeGenerator();
// register challenge variable
$chlgen->setChallengeVar();
/*
 * End of server-side processing
 */
?>
<!doctype html public "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>CHAP LOGIN SYSTEM EXAMPLE</title>
<script language="javascript" src="md5.js"></script>
<script language="javascript">
/*
 * validate form fields &
 * implement the Challenge Handshaking Authentication Protocol
 */
function checkForm(){
  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 $chlgen->getChallengeVar
'challenge')?>');
  // 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 'checkForm()' 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 checkForm();
    }
  }
}
</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>

With reference to the above snippet, you can appreciate that the programming logic is basically the same. I’ve only included the corresponding class for obtaining server-provided random seeds, but the rest of the script remains nearly identical. The only different piece of PHP code embedded into the markup involves calling to the “getChallengeVar()” method, illustrated in the following line:

chlng.value=MD5(MD5(psw.value)+'<?php echo $chlgen-
>getChallengeVar('challenge')?>');

To complete the example, the PHP script that runs on the server for authenticating the client might be written in the following way:

// include ‘challenge generator class’
require_once('challengeclass.php');
// include ‘MySQL abstraction class’
require_once('mysqlclass.php');
// instantiate a ChallengeGenerator object
$chlgen=&new ChallengeGenerator(false);
// get challenge variable
$challenge=$chlgen->getChallengeVar('challenge');
// get a "fresh" version of the page
header('Cache-control:must-revalidate');
// connect to MySQL
$db=new MySQLarray('host'=>'host','user'=>'user','password'=>'password',
'database'=>'database'));
// run query to obtain user data
$result=$db->query("SELECT userid,password FROM users WHERE
userid='".$_POST['userid']."'");
$row=$result->fetchRow();
// 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><body><h1>Thank you for logging in!
</h1></body></html>';
}
else{
  echo '<html><head><title>Access denied!</title><h1>Access
denied!</h1></body></html>';
}
// delete session data and destroy session
$chlgen->clearVars();

Using an object-oriented approach, the authenticating script is much simpler to read and understand. First, I’ve included the “ChallengeGenerator” class along with a “MySQL” wrapping class, useful for performing database-related tasks. Then, a new “ChallengeGenerator” object has been instantiated, in order to get the “challenge” session variable previously registered on the login script. These steps are performed with the code listed below:

// instantiate a ChallengeGenerator object
$chlgen=&new ChallengeGenerator(false);
// get challenge variable
$challenge=$chlgen->getChallengeVar('challenge');

Next, the script connects to MySQL, fetches the password and user ID that matches the ID entered by the user, and finally performs the client’s authentication by comparing the MD5 hashed values, in a manner similar to the process implemented in the procedural script. The following code is responsible for authenticating the client:

if(md5($row['password'].$challenge)==$_POST['challenge']&&$row
['userid']==$_POST['userid']){
  echo '<html><head><title>Login
Successful</title><body><h1>Thank you for logging in!
</h1></body></html>';
}
else{
  echo '<html><head><title>Access denied!</title><h1>Access
denied!</h1></body></html>';
}

At the end of the script, all of the session data is deleted and the session itself is destroyed:

// delete session data and destroy session
$chlgen->clearVars();

Now, you have an object-oriented script that uses a CHAP system for logging into a web-based application. Of course, it’s just a matter of taste and particular needs what approach you’ll use within your programs. In either case, the system’s effectiveness is the same, since in all cases passwords are never transmitted as plain text. Even if you’re not well versed in cryptographic techniques, you can still use their benefits for improving the overall security of your website’s login forms.

Conclusion

Over this series, I’ve explained the advantages of implementing CHAP systems on login forms, as an efficient and easy-to-use technique to raise the security level for transmitting sensitive data, and particularly passwords, during the execution of web-based programs.

Ranging from a procedural approach to an object-oriented method, you’ve been provided with enough code to play with, and start using the examples for your own convenience and purpose. Of course, I must thank Paul Johnston, who gently allowed me to use his excellent JavaScript MD5 library, throughout the examples developed in this series. Happy encrypting!


DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

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