Add a password to a php web page

PHP A password for what?

Sometimes you want to restrict the access to a webpage by adding a password (that you can share with other people). A good way to do that is to serve the webpage only if the user provide the correct credidentials. And to do that we need PHP (PHP Hypertext Preprocessor) to create the web page on the fly before sending it to the user.

The HTML5 skeleton

First we need to have a credidentials page written in regular HTML:

<!DOCTYPE HTML>
<html>
	<head>
		<title>Password page example</title>
	</head>
	<body>
		<header>
			<h1>Password page example</h1>
		</header>
		<!-- Password Form -->
		<form method="post" action="#">
			<input type="password" name="psw" placeholder="Password" required>
			<input type="submit" value="Validate" disabled>
		</form>
	</body>
</html>
		

PHP credidentials test

Now we need to check if the value store in $_POST["psw"] provided by the user corresponds to the real password. If no password was entered or a wrong password, we display the password form, with a error message when the password is wrong:

/* Test password */
if ( $_POST["psw"] !== "AVeryComplicatedPassword123456" ){
	/* Password form is shown if the authentification failed */
	echo '<form method="post" action="#">';
	echo '  <input type="password" name="psw" placeholder="Password" required>';
	echo '  <input type="submit" value="Validate">';
	echo '</form>';

	/* Wrong password message */
	if ( isset($_POST['psw']) ) {
		echo '<p>The password is wrong, try again or contact the administrator.</p>';
	}
}
Note: it is not a good idea to store your credit card number with this method (because the password is in clear on you server) but it is sufficent to quickly limit access on a specific webpage. More details are given below if you want to store securely passwords.

If the password is correct, we can display the expected text or/and web page :

else {
	/* Authentification success */
	echo '<p>You can see this text because you have the good password</p>';
	/* Or/and you can include an other page */
	include("mypage.html");
}

Try the whole page

Finally we put everyhting together into a single page:

<!DOCTYPE HTML>
<html>
	<head>
		<title>Password page example</title>
	</head>
	<body>
		<header>
			<h1>Password page example</h1>
		</header>
		<?php
 		/* Test password */
		if ( $_POST["psw"] !== "AVeryComplicatedPassword123456" ){
			/* Password form is shown if the authentification failed */
		        echo '<form method="post" action="#">';
			echo '  <input type="password" name="psw" placeholder="Password" required>';
			echo '  <input type="submit" value="Validate">';
			echo '</form>';

			/* Wrong password message */
			if ( isset($_POST['psw']) ) {
				echo '<p>The password is wrong, try again or contact the administrator.</p>';
			}
		} else {
			/* Authentification success */
			echo '<p>You can see this text because you have the good password</p>';
			/* Or/and you can include an other page */
			//include("mypage.html");
		}
		?>
	</body>
</html>
		

Going further and create sessions

If you want to keep the credidential all along your session, you need to store them into a global variable. In this case we can edit the code to start a session and use the $_SESSION PHP variable which is permanent other the sessions:

<!DOCTYPE HTML>
<html>
	<head>
		<title>Password page example</title>
	</head>
	<body>
		<header>
			<h1>Password page example</h1>
		</header>
		<?php
		/* Start credidential in a session */
		session_start();

		/* Close the session */
		if ( isset($_POST["logout"]) ){
			unset($_SESSION["AUTH"]);
		}

		/* Password authentification */
		if ( !$_SESSION["AUTH"] && $_POST["psw"] !== "AVeryComplicatedPassword123456" ){
			$_SESSION["AUTH"] = false;
		} else {
			$_SESSION["AUTH"] = true;
		}

 		/* Test authentification */
		if ( $_SESSION['AUTH'] ){
			/* Logout button */
		        echo '<form method="post" action="#">';
			echo '  <input type="submit" name="logout" value="Log Out">';
			echo '</form>';

			/* Authentification success */
			echo '<p>You can see this text because you have the good password</p>';
			/* OR/AND you can include an other page */
			//include("mypage.html");
		} else {
			/* Password form is shown only if the authentification failed */
		        echo '<form method="post" action="#">';
			echo '  <input type="password" name="psw" placeholder="Password" required>';
			echo '  <input type="submit" value="Validate">';
			echo '</form>';

			/* Wrong password message */
			if ( isset($_POST['psw']) ) {
				echo '<p>The password is wrong, try again or contact the administrator.</p>';
			}
		}
		?>
	</body>
</html>
		

Secure password storage

Writting password in plain text files is never a good idea. Anyone how can have access to the file will compromise its security. As usual, the less people know the password the more secure it will be. A good thing to do is to crypt the password (with crypt() in PHP). But to do that you need to use a cryptography key. If someone find it you are back to square one.

Then an other good idea is not to store the password directly but a footprint of it. So you don't know the real password but you can still check if the footprint of the password is identical to the one you know. This method is called hash (like SHA-1, MD5,...). The main drawback of this method is its sensibility to brute force attacks, raindow tables and dictionary attacks.

So the best way to avoid that is to mix the password with a random salt string (unique for each password) before crypting the hash. It seems to be complicated but in practice is not so difficult. That's how you should process to create the hash in PHP:

$password = 'gf45_gdf#4hg'; // Password to hash and crypt

// Create a unique random salt
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');

$cost = 10; // Define the level of cryptography (higher "cost" is more secure but consumes more processing power)

// Prefix information about the hash so PHP knows how to verify it later.
$salt = sprintf("$2a$%02d$", $cost) . $salt; // "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
// Output "salt" example: $2a$10$eImiTXuWVxfM37uY4JANjQ==

// Hash your password with the salt, and store it where you want.
$hash = crypt($password, $salt);
// Output "hash" example: $2a$10$eImiTXuWVxfM37uY4JANjOL.oTxqp7WylW7FCzx2Lc7VLmdJIddZq

Then in your password identification file, you just need to do the following test

// Hashing the password with its hash as the salt returns the same hash.
if ( hash_equals($hash, crypt($_POST['psw'], $hash)) ) {
  // Place here the part of the file that you want to protect.
}