Lab 10

Lab 10

Authentication & Sessions


Goals

Learn about...

  1. PHP Sessions
  2. Login/Authentication Implementation
  3. Integrating Scripts

FTP Connection Details


1. Creating a users table

  1. In your project2 folder, create a new file called create_users_table.php
  2. Add the following code, but change the table to use your username and not ea30brei
    <?
    require_once('site_db.php');
    
    $sql = "CREATE TABLE IF NOT EXISTS  `ea30brei_users` (
    	`userid` varchar(32) NOT NULL,
    	`passwd` varchar(128) NOT NULL,
    	`type` int(11) DEFAULT 0,
    	PRIMARY KEY (`userid`)
    )";
    
    run_query($sql);
    
    echo 'SUCCESS: The following query executed: '.$sql;
    ?>
  3. Note that this create a table for storing users including the user's password and a code for the type of user.
  4. Note that the script above will allow anyone who knows the URL to create the user table if it does not already exist.
  5. One way to ensure that only authorized users can excute this script is require a URL key.
  6. In general, a key is sufficiently complex string that would be difficult to guess and or "crack" using brute force.
  7. This can be added, with an if statement at the top of any script:
    if ($_GET['key'] != 'COMPLEXKEYGOESHERE') die ('Access Denied');
    
  8. The die function terminated the PHP process for the current request and prints a message.
  9. In our example, above the script must be called: create_users_table.php?key=COMPLEXKEYGOESHERE
  10. Add the if statement to your create_users_table.php, put pick a different key in the if statement.
  11. Upload the script to your project2 folder.
  12. Test the script on the server using your URL and key.
  13. First, try to run the script without the correct key in the URL to make sure "Access Denied" is printed.
  14. Second, run the script with the correct key to create your users table.
  15. Finally, use the URL show_columns.php?table=yourid_users to see if the table was created correct.

2. Using PHP Sessions to implement admin access

zyBook Chapter 13.4 describes cookies and session in great detail. Please review.

  1. The if statement in the previous part can secure any script and could be implemented as function and integrated into any framework.
  2. For example, we might want to secure a script for deleting tables, which is common if a table is not correctly created.
  3. However, typing a lengthy key in the URL for each secured script can be tedious for developers.
  4. Instead, we will create two special scripts (admin_login.php and admin_logout.php) so a developer only has to type the key once.
  5. The admin login script will create a session variable on the server and store a browser cookie to identify an admin user.

admin_login.php

  1. Create a file called admin_login.php and add the following code:
    <?
    session_start();
    	
    require_once('site_core.php');
    
    echo_head("Admin Login");
    echo '<div class="container">';
    
    if ($_POST[key] == "DF2C23C1FDFEA") {
      $_SESSION['authenticated'] = true;
      echo '<div class="alert alert-success">Admin Login Successful</div>';
    }
    else {
      echo '
        <form action="admin_login.php" method="post">
          <label>Key: <input type="text" class="form-control" name="key"></label>
          <input type="submit" class="btn btn-primary">	
        </form>';
    }
    
    echo '</div>';
    echo_foot();	
    ?>
  2. The script above is a great example of how a web application can implement a state for a particular user. In this case, the state is remembered using a PHP Session variable, i.e., $_SESSION['authenticated'] = true.
  3. Using sessions requires calling the start_session() function.
  4. Important: session_start() create a new PHP Session ID and then uses the HTTP protocol to send a request back to the web browser to set a PHP Session ID as a cookie for the server domain (username.sienacs.com or username.breimer.net). Once this cookie is set on the web browser, the HTTP protocol requires the web browser to send the PHP Session ID in any request to the server domain. Essentially, the server gives the user a unique name and then requires the user to identify itself on every subsequent request.

admin_logout.php

  1. Create a file called admin_logout.php and add the following code:
    <?
    session_start();
    session_destroy();	
    
    require_once('site_core.php');
    
    echo_head("Admin Logout");
    
    echo '
    <div class="container">
      <div class="alert alert-danger">Session destroyed. You are logged out.</div>
      <a href="admin_login.php" class="btn btn-primary">Login</a>
    </div>';
    
    echo_foot();	
    ?>
  2. Important: session_start() must be called to restore a previously started session.
  3. session_destroy() clears (destroys) all the data associated with the current session and then uses the HTTP protocol to send a request back to the web browser to delete the cookie, i.e., the PHP Session ID for the server domain.

Seeing if you are logged in

  1. Modify admin_login.php to detect if you are already logged in by adding the following if statement inside echoed container:
    if ($_SESSION['authenticated']) {
      echo '
        <div class="alert alert-info">Already logged in</div>
        <a href="admin_logout.php" class="btn btn-primary">Logout</a>';
    }
    else {
      // Add the login code, i.e., if statement to check the key matches, otherwise print the form
    }	
    

Protecting create_users_table.php

  1. Modify create_users_table.php to replace the if statement that uses a URL-passed key with the following:
    session_start();
    if (!$_SESSION['authenticated']) die ('Access Denied');
    

Implementing a protected delete_users_table.php

  1. In your project2 folder, create a new file called delete_users_table.php
  2. Add the following code, but change the table to use your username and not ea30brei
    <?
    session_start();
    if (!$_SESSION['authenticated']) die ('Access Denied');
    	
    require_once('site_db.php');
    
    $sql = "DROP TABLE `ea30breim_users`";
    
    run_query($sql);
    
    echo 'SUCCESS: The following query executed: '.$sql;
    ?>

TASK CHECK 1

Upload the four files you created to the server:

First, use the admin logout script to ensure that you are logged out and then try to run create_users_table.php and delete_users_table.php. You should get "Access Denied" messages.

Second, use the admin login script to login and then verify by refreshing the page which should output the "Already logged in" message.

Finally, use the following three scripts to verify that you can create and delete the users tables if you are logged in:

Due to a caching bug on the database server, your scripts might return old error messages indicating that the table cannot be found or already exisits. Thus, you must use the show columns script to verify if the table really exists or not.


2. Inserting & Deleting Users

Using your previous work as a model, write session protected scripts for inserting (insert_user.php) and deleting (delete_user.php) users so only an admin user can execute these script.

Remember to always call session_start() at the top of your scripts in order to access session variables.

Rather than store the password in the database as plain text, store a hashed password. Use $hashed_passwd = password_hash($passwd, PASSWORD_DEFAULT) to create a hashed password using PHP's built-in password hasing function, which will create a 60 character hash using all the best practices (SALT).

See the official PHP documentation on password_hash

Here is the SQL code for inserting a new user (note that we are inserting the hashed password, not the plain text password):

INSERT INTO yourid_users (userid, passwd, type) VALUES ('$userid','$hashed_passwd','$type')

Note that this is similar to your script for inserting pages, but the table name and field names are different and you must remember to hash the password before inserting it.

The delete user script is similar to the delete pages script, but the table name and primary key is different.

DELETE FROM yourid_users WHERE userid = '$userid'

3. Implementing a login with the users table (login.php)

Note that this script is not secured, i.e., admin only.

Using your admin_login.php as a model, write a login script (login.php) that asks for the user name and password.

Be sure to use <input type="password"> to enter the password so that the submitted password will be hidden

Instead of comparing the user submitted key with a hardcoded key value, compare the user-submitted password with the hashed password stored in the database. Use the PHP password_verify function as follows:

if (password_verify($user_submitted_password, $hashed_password)) {
  $_SESSION['authenticated'] = true;
  echo 'Password is valid!';
} else {
  echo 'Invalid password.';
}

See the official PHP documentation on password_verify

Remember to always call session_start() at the top of your script to set session variables.

Here is the SQL code to get the hashed password out of the database:

SELECT passwd FROM yourid_users WHERE userid = '$userid'

Remember this query will return one row with one column. Then you must fetch the row using either fetch_row() or fetch_assoc(). Finally, you must set $hashed_password to either $row[0] or $row['passwd'].

TASK CHECK 2

Upload the three files you created to the server:

Use admin_login.php so you can execute secured scripts.

First, create at least three new users and use the show_table.php?table=yourid_users to verify that they are created.

Second, delete one user and use the show_table.php?table=yourid_users to verify that the user was deleted.

Finally, test your login.php with the newly created users to verify that the session is only created if the submitted password matches the stored hashed password.

DELIVERABLE

Nothing. You get full credit for using the 2-hour lab time productively. You must finish this work as part of project3.

Not finished?

No problem. This lab is participation credit only. You must finish this work as part of project3.

Do not share

Do not share your work with any other student. This work is part of project3 and must be completed individually