Page: 1

Authentication and Sessions

Authentication is the process of identifying the participants in a communication. Authentication lets you

You may find out automatically which computer access your service, but if you want to identify the person, you will have to ask her.

In this lecture we will show how to perform HTTP user authentication and custom PHP/MySQL authentication with sessions.

Examples


Page: 2

HTTP Basic Authentication

Authentication is such a common task that authentication facilities are built in to the HTTP, called Basic Authentication.

This is the method used for the Intranet at IT-C.

It may be triggered by a server-script (e.g. PHP) or directly by the Web server (e.g. Apache or IIS).

Here is the general picture:

  1. The client requests the page index.php from the web-server
  2. A requests for authentication is send back to the browser, by returning an HTML-file with a header of the form
    WWW-Authenticate: Basic realm="IT University Intranet"
    HTTP/1.0 401 Autherization Required
  3. The page may look like
    WWW-Authenticate: Basic realm="IT University Intranet"
    HTTP/1.0 401 Authorization Required
    <body>
    <h1>Invalid login/password</h1>
     
     You must provide a valid login and password to enter this site.
    
    
    <p>
    <hr>
    <address>Apache/1.3.20 Server at www.it-c.dk Port 80</address>
    </body>
    
    
    

  4. The first header triggers the browser to open a dialogue box, prompting the user for user name and password
  5. If the user press Cancel or e.g. fails too many times, the rest of the authentication page is shown
  6. If the user press Ok, the user name and password are send (by default in plain text) to the web-server, which is then validated
  7. If the user has provided the correct password, the requested page is send back, otherwise the authentication request is resend


Page: 3

HTTP Basic Authentication with PHP

Let us see how to use HTTP Basic Authentication with PHP on the Apache web-server.

It relies on the environment variables PHP_AUTH_USER and PHP_AUTH_PW.

You may test it here. Notice that,


Page: 4

Making Passwords Secret using One-way Functions

Passwords can be made secret using a one-way function.

We use the the cryptographic hash function MD5 (Rivest, 1992), also called a message digest.
It has the following four important properties:

  1. Given a string "somestring", it is easy (fast) to compute md5("somestring")
  2. Given md5("somestring"), it is effectively impossible to find "somestring".
  3. Given "somestring", it is effectively impossible to find "anotherstring" such that md5("somestring")=md5("anotherstring")
  4. Changing one bit of the input produces a very different output

Examples

md5("MyPass")=

md5("Homer")=

md5("NyPass")=

Protecting the Password with MD5

We can now substitute the validation line with:
if ($PHP_AUTH_USER == "hilde" && md5($PHP_AUTH_PW); == "fb3f06c821388858cafe95cea24895d3") $auth = true;

The first point above ensures that the validation is fast.

The second point above ensures that it is effectively impossible to find the password from the script


Page: 5

Saving Usernames and Passwords in the Database

Often we will want several users with different passwords to be able to log in.

We might also want to allow new users to register, or old users to change passwords.

In this case we should store the password information in a database or in a file.

We might create a Users table and inserte a couple of users as follows:

CREATE TABLE `Users` (
`name` CHAR(10) NOT NULL,
`passwd` CHAR(32) NOT NULL,
PRIMARY KEY (`name`),
UNIQUE (`name`)
)
INSERT INTO Users (name, passwd) VALUES
("Thomas",MD5("MyPass")),
("Homer",MD5("Homer"));

Note the use of MD5 in MySQL.

The following code implements a password check against the Users table, assuming that connect() makes a connection to the Database containing the table.

You may test it here.


Page: 6

HTTP Basic Authentication with Apache's .htaccess files

You can avoid server-script programming, by using the Apache server's mod_auth authentication module and .htaccess files.

It is done by placing an .htaccess file in a directory, which will control accesses to files and any subdirectories in this directory.

The .htaccess file may look like
AuthUserFile /import/home/hilde/Webprogramming/.htpass

AuthName "Web Programming Secret Pages"

AuthType Basic

require valid-user

The line
AuthUserFile /import/home/hilde/Webprogramming/.htpass
specifies the text file in which the user names and passwords is recorded.

This page should NOT be in the web-tree...

The line
AuthName "Web Programming Secret Pages"
specifies the name of the access restricted area of the web-site.

The remaning lines
AuthType Basic
require valid-user
specify the authentication method (Basic) and who is allowed to pass (any authenticated user).

The file .htpass may look like
hilde:NRSDtsceWfu0I
henrik:aiM.//KZIbzGo

Note that the passwords are stored in encrypted form. You might perform the encryption yourself using the PHP function crypt
which can be tested here.

Note that the crypt function uses a salt to generate the encryption.

In the .htpass file, the salt can be recovered as the two first characters of the encrypted string. (In fact the crypt function supports several encryption types, see here which encryption types are supported. Read more in the php manual).

We do not need to write a PHP script. The password file can be automatically generated with the program htpasswd that comes with the Apache distribution.

Below is shown the steps I took to generate a password file with two users.
> htpasswd -bc .htpass  hilde WP
Adding password for user hilde
> htpasswd -b .htpass henrik pass
Adding password for user henrik
> more .htpass
hilde:NRSDtsceWfu0I
henrik:aiM.//KZIbzGo
The c option tells htpasswd to generate a new file.
The b option tells htpasswd to expect the password as a parameter.

You may test the above authentication here. Try first not to provide a valid password.

Note that


Page: 7

Custom Authentication with PHP: A custom form

From the lecture on PHP page 14 we know how to present a form.

Below you can see a part of the file secret.php.


Page: 8

Saving State with Cookies

The HTTP protocol is stateless. In order to remember that the user has logged in when proceeding to a new page we need to record the state. This might be done by saving a cookie at the browser machine. Browsers like Netscape and IE support cookies, however, users may choose not to accept them and some platforms (e.g. WAP) do not (always) support cookies.

A cookie is introduced to the client by including a Set-Cookie header as part of an HTTP response. The header has the form:
Set-Cookie: NAME=VALUE; expires=DATE;
path=PATH; domain=DOMAIN_NAME; secure
This header can be generated by the PHP-function setcookie (string NAME [, string VALUE [,int EXPIRE [,string PATH [, string DOMAIN_NAME [,int secure]]]]]) as illustrated in the example below.
<?
setcookie ("pass", $pass,time()+600);    /* expires in 10 minutes */
setcookie ("user", $user,time()+600);    /* expires in 10 minutes */
?>
Once the cookies have been set, they can be accessed on the next page load, directly or with the $_COOKIE (PHP 4.1.0) or $HTTP_COOKIE_VARS arrays.

You delete cookies again by calling the function setcookie() with the same name, but without a value. This sets a header with the same name (and path), but an expires time in the past.
<?
setcookie ("pass");
setcookie ("user");
?>

Since cookies are set by headers it is important not to set them before any other data is output. Moreover, cookie headers must be set before any other headers, as e.g. the authentication header.

You can read more about cookies in the specification at Netscape's site.

It is generally not a good idea to store the password and other sensitive data in a cookie.

Instead one should generate a unique session ID, and only store this session ID at the client. At the server one then records which user-specific data is related to this session ID. When the user logs out (or after a certain period of time) this information on the server can be deleted.


Page: 9

Saving State with Sessions

Using PHP sessions you can avoid managing generation of session ID's and saving values at the server. The basic steps are

  1. Starting the session
  2. Register session variables
  3. Do your business in the session (using the variables)
  4. Deregister session variables
  5. Stop (Destroy) the session
A nice security feature of session variables is, that they cannot be overridden by GET and POST data (i.e. using parameters).

However, they might be set by GET and POST data, if they are not set already. Use the function session_is_registered("pass") instead of isset("pass").

The behaviour of PHP-sessions depends on a number of parameter settings in the configuration of PHP (defined in the php.ini file).

As usual, you can see the values by calling phpinfo();

Session options briefly

session.name: This is the name used as cookie/parameter name.

session.cookie_lifetime: Lifetime of cookie in seconds. Value 0 (default) means until browser (all windows) is closed.

session.use_cookies: Whether to user cookies or URL parameters.

register_globals: If "On" you can register all global variables, and access the variables as usual, as in the example above.
If "Off", you can only use entries of the associative array $HTTP_SESSION_VARS (or $_SESSION from PHP 4.1.0) as session variables, e.g. $HTTP_SESSION_VARS["pass"]. These variables do not need to be registered and unregistered.

session.use_trans_sid: If true (1) the session Id is embedded automatically in the local URLs.

session.save_handler: Default set to "files". You can implement your own handler methods, e.g. to use a database - useful if sessions should work cross several web-servers.

You can change many of the configuration parameters for the duration of a script using the ini_set() function. The session parameters can also be changed using specialised functions, e.g. session_set_cookie_params(int lifetime [, string path [, string domain [, bool secure])


Page: 10

Saving State with Sessions Example

Starting a session registering two variables may look like page1.php below
<? 
 session_start();

 session_register("name","pass");

 if (session_is_registered("pass") && session_is_registered("name"))
     echo "<h1>name and password variables registered</h1>";

 $name = "hilde";
 $pass = "mypassword";

 echo "<h1>Session variables set!</h1>";
 echo "<a href=\"page2.php\">go to next page</a>";

?>

The next page, page2.php, might look like
<? 
 session_start();

 echo "<h1>The password of $name is $pass </h1>";

 session_unregister("pass");

 echo "<h2>password unregistered </h2>";

 echo "<a href=\"page3.php\">go to next page</a>";

?>
You may unregister all variables by calling session_unset();.

In the third page, page3.php, we do not have access to the variable pass anymore.
<? 
 session_start();
 echo "<h2>name is  $name </h2>";

 echo "<h2>password is  $pass </h2>";

 session_unregister("name");

 echo "Name unregistered, but name is set to $name until end of this script...";

 session_destroy();
 echo "<a href=\"page4.php\">go to next page</a>";

?>
page4.php
<? 
 session_start();
 echo "<h2>name is  $name </h2>";

 echo "<h2>password is  $pass </h2>";

 session_destroy();
 echo "<a href=\"page1.php\">go back to page 1</a>";
?>


Page: 11

Fine-grained Authentication Example: Personal Phone Book

We end by giving an example of a fine-grained authentication.

It uses


You can test the Personal Phone Book here.


Page: 12

Secure Socket Layer

None of the techniques presented so far are really secure. The HTML pages send to your browser can be read by anyone, passwords can be sniffed and session ID's can be hijacked.

You should use HTTP on top of SSL (HTTPS) if you are handling sensible data.

SSL uses public-key encryption (slow, but secure) to establish a connection (the SSL handshake) and uses symmetric key encryption (fast, not as secure) after the connection has been established. If RSA Key Exchange is used the handshake works as follows:

  1. The browser connects to an SSL enabled server and asks the server to authenticate itself, sending a client_hello message containing the supported SSL version number and cipher algorithms
  2. The server selects the strongest cipher suite it supports and responds with a server_hello message, containg this information (and optionally request the browser to authenticate itself)
  3. The server sends its certificate.
  4. The client verifies the server certificate, which contains (among other things): the servers public-key, the server-name (e.g. www.itu.dk), a validity period and information about the Certificate Authority (CA) that has signed the certificate (e.g. Verisign or Thawte).
  5. The client sends a client_key_exchange message containing a 48 byte pre-master secret encrypted with the public key from the server certificate
  6. The client computes a shared master secret based on the pre-master secret.
  7. The server computes the same shared master secret based on the pre-master secret. Only the server having the private key can do this.
  8. The client and server starts communicating using symmetric key encryption based on the shared master secret.
This procedure takes time, but fortunately the results are cached, so it is only needed once.

You can read a more detailed Introduction to SSL (Sun) and look at netscape's site.


Page: 13

Authentication and Sessions Summary

  1. The HTTP protocol provides an easy way to introduce authentication using the Authorization header, this can be triggered by a PHP script or by the web-server
  2. You should apply a one-way function to passwords
  3. You might implement your own fine-grained authentication and save state using URL-parameters/cookies/sessions
  4. None of the techniques are really secure - use HTTP on top of SSL (HTTPS) if you are handling sensible data

Resources


Page: 14

Exercises in Authentication and Sessions

  1. JavaScript in Authentication: (Similar to an exam exercise from exam E2001, 10 %)
    Consider the following HTML document, presenting a password change form

    Add the necesarry JavaScript code such that the form only can be submitted if
  2. Sessions: (Exam exercise from exam E2001, 10 %) Consider the PHP-script storytime.php below. It writes a line from a scary story, depending on the value of$page

    Extend the program with a PHP session such that the first line is written first time the script is requested by a user, and each time he request it subsequently the next line of the story is written. The story should start over after the last line "scary night." has been shown.

  3. Authentication using PHP and MySQL: Consider the Personal Phone Book example. Copy the code to your own folder, create your own PPhoneBook table (as in the PhoneBook database in the MySQL lectures) in your own database, and create a Users table and insert a number of users with MD5 hashed passwords (as in the Authentication lecture).
    Change (do one step at a time) the Personal Phone Book such that
    1. The edit link is not present if the user has not made a correct login
    2. New users can sign up, using a form with three fields: name, password and retypepassword. You should check that the same password has been given in the two password fields, using JavaScript as in the first exercise. You should make sure that two users are not allowed to have the same name. Remember to store the passwords hashed with MD5.
    3. It is recorded in the database for each entry, which user entered the entry. Start out with a fresh phonebook table, you may change the layout of your database.
    4. A user can only edit and delete his own entries.

    Optional Hand-In

    The News Example II: Add authentication to the news example and allow users who has made a correct login to:
    1. Add new articles (record the name of the author)
    2. Edit/delete (their own) articles
    use sessions as in the Phonebook exercise above.