Login   Register  
PHP Classes
elePHPant
Icontem

File: AuthenticatorDemo.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Claudius Tiberiu Iacob  >  Authenticator_ciacob  >  AuthenticatorDemo.php  >  Download  
File: AuthenticatorDemo.php
Role: Example script
Content type: text/plain
Description: See "HoToInstall.txt" for info
Class: Authenticator_ciacob
Register and authenticate users
Author: By
Last change: Changed listing priority.
Date: 2010-02-03 08:38
Size: 16,645 bytes
 

Contents

Class file image Download
<?php

	require_once ('domit/xml_domit_include.php');
	require_once ('ParamsProxy.php');
	require_once ('UTF8.php');
	require_once ('DbProxy.php');
	require_once ('Authenticator.php');

	/**
	* Showcases the functionality of the Authenticator class.
	* The Authenticator class is an users registrar kernel. It provides low-level API for user
	* registration, login and credentials management.
	*
	* @author Claudius Tiberiu Iacob <claudius.iacob@gmail.com>.
	* @license Creative Commons Attribution Share Alike - Claudius Tiberiu Iacob 2009
	*/
	class AuthenticatorDemo {

		/**
		* Logs in an user. For simple, open registration (which is our case), this is done as:
		*
		* Authenticator::getInstance()->authenticate (<password>, <username>);
		*/
		private function loginUser () {
			$userPass = trim ($_POST['pass']);
			$userName = trim ($_POST['username']);
			if (!empty ($userName) && !empty ($userPass)) {
				$sessionData = Authenticator::getInstance()->authenticate ($userPass, $userName);
				$isAuthenticated = !is_numeric ($sessionData);
				if ($isAuthenticated) {
					$this->storeSessionData ($sessionData);
					$this->gotoProtectedContent();
				} else {
					$errorMessage;
					switch ($sessionData) {
						case Authenticator::UNKNOWN_USER_PASS_COMBO:
							$errorMessage = 'wrong username and/or password.';
							break;
						case Authenticator::USER_HAS_NOT_CONFIRMED_REGISTRATION:
							$errorMessage = 'you must confirm your registration first';
							break;
						default:
							$errorMessage = "Error no. $sessionData.";
							break;
					}
					$this->makeMessagePage (
						'Login Failed',
						"Cannot authenticate you: $errorMessage."
					);
				}
			} else {
				$this->makeMessagePage (
					'Missing Credentials',
					'Please provide credentials in order to login.');
			}
		}

		/**
		* Attempts authentication with cached unique session id. Upon succes, a new unique session id
		* is produced, which you must cache instead of the old one. This is done as follows:
		*
		* Authenticator::getInstance()->authenticate (<session uniqe id>);
		*/
		private function attemptToLoginFromCache () {
			$isAuthenticated;
			$newSessionData;
			$cachedSessionData = trim ($_COOKIE["AuthenticatorDemo"]);
			if (!empty ($cachedSessionData)) {
				$newSessionData = Authenticator::getInstance()->authenticate ($cachedSessionData);
				$isAuthenticated = !is_numeric ($newSessionData);
			}
			if ($isAuthenticated) {
				$this->storeSessionData ($newSessionData);
				$this->gotoProtectedContent();
			}
		}

		/**
		* Recovers a forgotten passwords. This is done as:
		*
		* Authenticator::getInstance()->retrievePassword (<registration e-mail address>);
		*
		* If the Authenticator module has been set to drop support for password recovery, then the same
		* API above will reset the passsword to a random value and return that random value instead.
		*/
		private function recoverUserPassword () {
			$email = trim ($_POST['email']);
			if (!empty ($email)) {
				$passwordData = Authenticator::getInstance()->retrievePassword ($email);
				// Passwords cannot be shorter that 4 chars; if this is the case, we deal with an error
				// number:
				$recoveryFailed = (is_numeric ($passwordData) && strlen($passwordData) < 4);
				if ($recoveryFailed) {
					$errorMessage;
					switch ($passwordData) {
						case Authenticator::UNKNOWN_EMAIL:
							$errorMessage = "The e-mail $email was never registered.";
							break;
						default:
							$errorMessage = "Error no. $passwordData.";
							break;
					}
					$this->makeMessagePage (
						'Error',
						$errorMessage
					);
				} else {
					$this->sendEmail (
						$email,
						'AuthenticatorDemo <noreply@nowhere.com>',
						'Your password to AuthenticatorDemo',
						"This is your forgotten password to AuthenticatorDemo (leave out the ".
						"enclosing quotes and trailing dot):\n".
						"\"$passwordData\".");
					$this->makeMessagePage (
						'Password Recovered',
						"An e-mail has been sent to you at $email, containing your forgotten password."
					);
				}
			}
		}

		/**
		* Registers an user. For simple, open registration (which is our case), this is done as:
		*
		* Authenticator::getInstance()->register (array (Authenticator::PASSWORD => <password>),
		* 	<username>, <email>);
		*/
		private function registerUser () {
			$username = trim ($_POST['username']);
			$email = trim ($_POST['email']);
			$pass = trim ($_POST['pass']);
			$passAgain = trim ($_POST['passAgain']);
			if (!empty ($username) && !empty ($email) && !empty ($pass) && !empty ($passAgain)) {
				if ($pass !== $passAgain) {
					$this->makeMessagePage (
						'Missmatched Password',
						'Please enter the same password twice.'
					);
				} else {
					$confirmationData = Authenticator::getInstance()-> register (
						array (Authenticator::PASSWORD => $pass), $username, $email);
					$isUserRegistered = !is_numeric ($confirmationData);
					if ($isUserRegistered) {
						$this->sendEmail (
							$email,
							'AuthenticatorDemo <noreply@nowhere.com>',
							'Please confirm your registration to AuthenticatorDemo',
							"Copy & paste in your browser's address bar the following URL (leaving ".
							"out enclosing quotes):\n".
							"\"" . $this->makeConfirmationURL ($confirmationData) . "\"");
						$this->makeMessagePage (
							'Confirm Registration',
							"An e-mail has been sent to you at $email.
							Please follow the confirmation link contained in this e-mail in order to
							complete registration."
						);
					} else {
						$errorMessage;
						switch ($confirmationData) {
							case Authenticator::ILLEGAL_USER_NAME:
								$errorMessage = 'Provided user name is not acceptable.';
								break;
							case Authenticator::ILLEGAL_EMAIL:
								$errorMessage = 'Provided e-mail is not acceptable.';
								break;
							case Authenticator::ILLEGAL_PASSWORD:
								$errorMessage = 'Provided password is not acceptable.';
								break;
							default:
								$errorMessage = "Error no. $confirmationData.";
								break;
						}
						$this->makeMessagePage (
							'Error',
							$errorMessage
						);
					}
				}
			} else {
				$this->makeMessagePage (
					'Missing Data',
					'Please provide all required data in order to sign up.'
				);
			}
		}

		/**
		* Completes registration for a self-registering user. This is done as:
		*
		* Authenticator::getInstance()->register (array (Authenticator::CONFIRMATION_UID => <uid>));
		*/
		private function completeRegistration ($confirmationUid) {
			$confirmationAnswer = Authenticator::getInstance()->register (
				array (Authenticator::CONFIRMATION_UID => $confirmationUid));
			$isConfirmed = (!is_numeric ($confirmationAnswer));
			if ($isConfirmed) {
				// If confirmation is successfull, the returned result is a valid session unique id.
				//
				// In this example, you could use the $confirmationAnswer variable to automatically
				// authenticate the user, rather than printing a confirmation message.
				$this->makeMessagePage (
					'Registration Complete',
					'You have successfully signed up to AuthenticatorDemo. You may now proceed to the
					Login Page, and authenticate using your supplied credentials.'
				);
			} else {
				$errorMessage;
				switch ($confirmationAnswer) {
					case Authenticator::IVALID_CONFIRMATION_UID:
						$errorMessage = 'Provided confirmation unique id is invalid. Have you
							entered the URL correctly?';
						break;
					case Authenticator::EXPIRED_CONFIRMATION_UID:
						$errorMessage = 'Provided confirmation unique id has expired. You will need
							to sign up again.';
						break;
					default:
						$errorMessage = "Error no. $confirmationAnswer.";
						break;
				}
				$this->makeMessagePage (
					'Error',
					$errorMessage
				);
			}
		}

		/**
		* Stores the session unique id on the client machine.
		*
		* You must locally store the session id yourself; the Authenticator module doesn't do it for
		* you.
		*
		* The session lifetime is limited by the Authenticator module, internally. If you use a
		* cookie as the local storage medium, give it a long lifetime. This will rule out potential
		* issues. In this demo, we make the cookie last one day, although our Authenticator is
		* configured to allow 15 minutes per session at most.
		*/
		private function storeSessionData ($sessionData) {
			$cookieExpireTime = (time() + 86400);
			$cookiePath = '/';
			setcookie ('AuthenticatorDemo', $sessionData, $cookieExpireTime, $cookiePath);
		}

		/**
		* Concatenates an URL containing confirmation data.
		*
		* The Authenticator module doesn't produce confirmation URLs for you, therefore you must carry
		* on this aspect by yourself.
		*/
		private function makeConfirmationURL ($confirmationData) {
            $url = ($_SERVER['HTTPS'] == "on")? 'https://' : 'http://';
            $url .= $_SERVER['HTTP_HOST'];
            if ($_SERVER['SERVER_PORT'] != '80') {
                $url .= (':' . $_SERVER['SERVER_PORT']);
            }
            $path = str_replace ($_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
            $url .= $path;
            if (strpos ($url, '?') !== strlen ($url) - 1) {
            	$url .= '?';
            }
            $url .= ('confirmation=' . $confirmationData);
            return $url;
		}

		/**
		* Sends a plain text e-mail.
		*
		* The Authenticator module doesn't deal with sending e-mails. You must write your own code to do
		* that.
		*/
		private function sendEmail ($to, $from, $subject, $message) {
			$message = wordwrap ($message, 70, "\n", true);
			$headers =
				"From: $from\n" .
			    "Reply-To: $from\n" .
			    'X-Mailer: PHP/' .phpversion(). "\n";
			$addParam = "-f$from";
			$result = @mail ($to, $subject, $message, $headers, $addParam);
			return $result;
		}

		/**
		* @constructor
		*
		* This logic is essentially a state machine. It detects the action to be performed and invokes
		* the associated class method.
		*
		* The Authenticator module only provides you core functionality; you must aggregate it yourself
		* in order to build/integrate with a user control panel page.
		*/
		public function __construct () {
			$this->blindlyInitialize ();
			$action = trim ($_POST['action']);
			switch ($action) {
				case 'Sign me in':
					$this->loginUser();
					break;
				case 'E-mail me':
					$this->recoverUserPassword();
					break;
				case 'Sign me up';
					$this->registerUser();
					break;
				case 'login page':
					$this->makeLoginPage();
					break;
				case 'password recovery page':
					$this->makeRecoverPassPage();
					break;
				case 'registration page':
					$this->makeRegistrationPage();
					break;
				default:
					// If we are given a confirmation unique id, then complete registration for that
					// unique id:
					$confirmationUid = trim ($_GET['confirmation']);
					if (!empty ($confirmationUid)) {
						$this->completeRegistration ($confirmationUid);
						return;
					}
					// Otherwise, attempt to re-login using cached session data:
					$this->attemptToLoginFromCache();
					// If we have no valid session data, we load the login page:
					$this->makeLoginPage();
					break;
			}
		}

		/**
		* @destructor
		*/
		public function __destruct () {
			$this->makePageFooter ();
		}

		/**
		* DO NOT, UNDER NO CIRCUMSTANCE, blindlyInitialize() THE AUTHENTICATOR MODULE IN A REAL WEB
		* APPLICATION!
		*
		* This method FAKES a real initialization for the Authenticator module. We do it in order to
		* keep our demo's user interface as simple as possible.
		*
		* Because this is a demo, and because we included no administrative features in this demo,
		* we will initialize the Authenticator module in the background, using hardcoded master
		* credentials. For real-life scenarios though, master credentials are essential. You will
		* typically create a page in your web application that initializes master credentials and sends
		* them to your e-mail address. Beware not to make this the default page of your web application.
		* It is also common practice to delete this page once setup is complete.
		*
		* The API used for initializing master credentials looks like:
		*
		* <result> = Authenticator::getInstance()-> register (
		* 		array (Authenticator::PASSWORD => <mster password>), <master user name>,
		* 		<master e-mail>, 'master');
		*
		* You must register one master account before being able to use the Authenticator. Master
		* registration locks itself after a master account has been defined.
		*/
		private function blindlyInitialize () {
			$sessionData = Authenticator::getInstance()->authenticate ('demo', 'demo', 'master');
			$hasMaster = ($sessionData !== Authenticator::MASTER_NOT_SET);
			if ($hasMaster) {
				$isAuthenticated = !is_numeric ($sessionData);
				if ($isAuthenticated) {
					Authenticator::getInstance()->unAuthenticate ($sessionData);
				}
			} else {
				Authenticator::getInstance()-> register (array (Authenticator::PASSWORD => 'demo'),
					'demo', 'demo@nowhere.com');
			}
		}

		// Less relevant class methods (printing and redirection)...
		private function makePageHeader () {
			echo '<?xml version="1.0" encoding="UTF-8"?>
			<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
			    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
			<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
			  <head>
			    <title>AuthenticatorDemo</title>
			  </head>
			  	<body>';
		}

		private function makeLoginPage () {
			$this->makePageHeader ();
			echo '
				<h2>Login Page</h2>
				<form method="post" action="">
					<h3>Sign in</h3>
					<p>
						<label>
							User name:
							<input type="text" name="username" />
						</label>
					</p>
					<p>
						<label>
							Password:
							<input type="password" name="pass" />
						</label>
					</p>
					<p>
						<input type="submit" name="action" value="Sign me in" />
					</p>
				</form>
			';
		}

		private function makeRecoverPassPage () {
			$this->makePageHeader ();
			echo '
				<h2>Password Recovery Page</h2>
				<form method="post" action="">
					<h3>Forgot Password?</h3>
					<p>
						Enter your e-mail address below, so we can send you your password. You
						must provide the same address you used at registration time.
					</p>
					<p>
						<input type="text" name="email" />
					</p>
					<p>
						<input type="submit" name="action" value="E-mail me" />
					</p>
				</form>
			';
		}

		private function makeRegistrationPage () {
			$this->makePageHeader ();
			echo '
				<h2>Registration Page</h2>
				<form method="post" action="">
					<h3>Sign Up</h3>
					<p>
						You need a valid e-mail address to sign up. A confirmation link will be sent
						to this address once you click the <em>Sign me up</em> button. You have
						follow this link in order to complete registration.
					</p>
					<p>
						<label>
							Username:
							<input type="text" name="username" />
						</label>
					</p>
					<p>
						<label>
							E-mail address:
							<input type="text" name="email" />
						</label>
					</p>
					<p>
						<label>
							Password:
							<input type="password" name="pass" />
						</label>
					</p>
					<p>
						<label>
							Password again:
							<input type="password" name="passAgain" />
						</label>
					</p>
					<p>
						<input type="submit" name="action" value="Sign me up" />
					</p>
				</form>
			';
		}

		private function makeMessagePage ($title, $content) {
			$this->makePageHeader ();
			$ret = '
				<h2>' . $title . '</h2>
				<p>' . $content . '</p>';
			echo $ret;
		}

		private function makePageFooter () {
			echo '
				<form method="post" action="">
					<hr />
					<p>
						Go to:
						<input type="submit" name="action" value="login page" />
						<input type="submit" name="action" value="password recovery page" />
						<input type="submit" name="action" value="registration page"/>
					</p>
				</form>
			</body>
			</html>';
		}

		private function gotoProtectedContent () {
			header ('Location: ProtectedContent.php');
			exit ();
		}
	}
	$authenticatorDemo = new AuthenticatorDemo();
?>