Apache2 Module 'mod_auth_form'

Current Version: 2.04

Contents


Overview

This module is a form-based authorization module based on 'mod_auth_mysql' and 'mod_auth_sim'. It is used to place access restrictions on a per-directory, per-user-request basis using session management. The module uses a MySQL database to retrieve users' group membership, maintain and validate users' sessions, and optionally track user activity.

The mechanics of the module works in the following way. A web client (user) requests for a restricted page/directory. The module sends back a 'Page Has Moved' error, pointing the client to the page containing a login form. Through server-side scripting, a session is created in the MySQL database and the client (i.e. cookies or query string). The session itself consists of a unique, random, and temporary ID that is associated with a user. The client then makes the same request along with the session ID (SID) and the user ID (UID). The module compares and validates the two IDs against the IDs stored in the MySQL database. If successful, the module sends back the requested page; otherwise, the module once again sends back the 'Page Has Moved' error page. In addition (if specified), the module will also validate the user's group membership and act accordingly.

Additional Notes:
1) This module does not verify username and passwords (not yet). The verification is left up to the web developer via server-side scripting. For example, if .htpasswd files are used, a Perl script can be written to verify a user's input against a .htpasswd file; if the user is verified, the same Perl script will create a session in the user's browser (cookies or query string) and in a MySQL database.

2) Do not use Apache's basic authentication directives with this module (exceptions are 'AuthType Basic' and 'AuthName "Name"'). Doing so may cause Apache to use basic authentication whenever a user accesses a restricted page. (See mod_auth and similiar modules).

3) To turn off 'mod_auth_form' for certain directories, add the directive "AuthFormAuthoritative Off" to the directory container. This is only useful when applying a different authentication module (e.g. mod_auth) to a directory under mod_auth_form's control (usually sub-directories).

4) This module requires SELECT permission at minimum. For 'AuthFormSessionTimeout', UPDATE is also required. For the tracking table, the module also requires INSERT, DELETE, and UPDATE permissions.

5) Enclose MySQL keywords with backticks (`) when using the 'AuthFormMySQL*' directives,. For example, "AuthFormMySQLFieldUID SELECT" needs to be "AuthFormMySQLFieldUID `SELECT`".

6) Use caution when specifying a fixed number of seconds for AuthFormSessionAutoRefresh. This option does not work well with inline frames that point to other auto-refreshing documents. If you have a restricted page with inline frames, you may need to specify "AuthFormPageAutoRefresh mypage.html" for each framed document.

7) 'AuthFormMySQLTableGID' should refer to a join table if each user is to be associated with multiple groups (where 'AuthFormMySQLFieldUID' and 'AuthFormMySQLFieldGID' are the join table attributes). Although this module allows multiple values for the 'AuthFormMySQLFieldGID' field, use only one value per record. This multi-value feature will be removed in the next major version (3.0).

8) This module may be renamed to mod_authnz_form for the next major version (3.0). The next major version (and maybe the 2.x series) will support authentication via HTTP POST along with session management, hence the 'nz' after 'auth'.

Requirements

Downloads


Minimum Installation and Configuration

Download the module and copy 'mod_auth_form.so' (and 'mod_auth_form.pdb' on win32) to the modules directory in the Apache2 distribution. Add the following lines to 'httpd.conf'.

LoadModule auth_form_module modules/mod_auth_form.so

# Directory and/or .htaccess statements
AuthType Basic
AuthName "Realm Name" # This has no effect, but it is required by Apache2.
AuthFormMySQLDB MySQL_Database
AuthFormPageLogin The_Login_Page_URL
Require valid-user

Under MySQL, create the following. Restart Apache2.

Examples

Case Study 1: A Simple Restricted Area: A website will contain a restricted area that requires a valid username and password. The restricted area itself is a directory called '/restricted'; the login pages for that restricted directory are '/login.html' and its handler '/login.php'. The MySQL server resides on the same computer as the Apache server, and the name of the database is 'users'. To implement this restricted area, the following must be done: Case Study 2: A Complex Member's Area: A website will contain a member's area that requires a valid username and password. The member's area itself is a directory called '/members'; furthermore, there are two more restricted directories called '/members/paying', which is for paying members only (where as '/members' is for any member) and '/members/paying/premium', which is for buisness customers and/or premium members. For added security, all sessions will expire either from 30 minutes of inactivity or 8 hours from the time of login; also, sessions are valid if two SID cookies matches and either the UID cookie or the directory's signature matches (in case the UID cookie is rejected). The login pages for the member's area are '/member_login.html' and its handler '/member_login.php'. The MySQL server resides on a host called 'fake_server.com', and the name of the database is 'members'. Also, the MySQL server will keep tracking records of each request made within the member's area.

For additional complexity, another directory called '/administration' will be accessed locally by the website maintainers. This directory will use basic authentication from 'mod_auth' using a password file located at '/absolute/path/to/passwords'.

To implement this member's area, the following must be done:
Logging Out: Besides session expiration, logging out of a session is done simply by deleting the session's record from the MySQL database. In addition, the client's cookies can be expired if cookies are used. Here is a PHP script for destroying a session, assuming the client passes the session cookies.
<?php
$uid = $_COOKIE["uid"];
$sid = $_COOKIE["sid"];
$mysql = new mysqli("mysql_host", "my_username", "my_password", "my_database");
$mysql->query("DELETE FROM sessions WHERE sid='$sid'");
$mysql->close();
setcookie("uid", $uid, time() - 964224000);
setcookie("sid", $sid, time() - 964224000);
header("Location: login_page");
?>

Configuration Reference

The directives listed below have the prefix AuthForm.

Authoritative
Flag : DEFAULT="On"
Turn on 'mod_auth_form'.

LastPageKey (version 2.02+)
String : OPTIONAL
The name of the url query string key containing the URL that a client unsuccessfully accessed (i.e. the URL from which the client was redirected).

MySQLDB
String : REQUIRED
The MySQL database to connect to.

MySQLFieldDownloadDate
String : DEFAULT="download_date"
Field under the tracking table that stores the time of request.

MySQLFieldDownloadPath
String : DEFAULT="download_path"
Field under the tracking table that stores the path of request.

MySQLFieldDownloadSize
String : DEFAULT="download_size"
Field under the tracking table that stores the size of request.

MySQLFieldExpiration
String : OPTIONAL
Field under the session table that stores the time the session will expire regardless of user activity. Not specifying this configuration disables session expiration (although session inactivity timeout can still be enabled). Also, AuthFormPageExpired must be configured.

MySQLFieldGID
String : DEFAULT="gid"
Field under the group table that stores the user's space/comma delimited list of group IDs.
NOTE: Having a multi-value field violates the conceptual design of relational databases. In the next major version (3.0), this feature will be removed in favor of a join table.

MySQLFieldIPAddress
String : DEFAULT="client_ip_address"
Field under the tracking table that stores the client's IP address.

MySQLFieldTimeout
String : DEFAULT="timeout_date"
Field under the session table that stores the time the session will expire if the user is inactive.

MySQLFieldUID
String : DEFAULT="uid"
Field under the session, group, and tracking tables that stores the user ID.

MySQLHost
String : DEFAULT="localhost"
The fully-qualified name or IP address of the MySQL server.

MySQLPassword
String : DEFAULT=<Blank Password>
The MySQL user's password.

MySQLPort (version 2.03+)
Number : DEFAULT="3306"
The MySQL port to connect to.

MySQLSSL (version 2.04+)
Flag : DEFAULT="Off"
Use SSL connections to MySQL. Please see the AuthFormMySQLSSL* directives. Those directives mimic the parameters in mysql_ssl_set() from the MySQL Client API.

MySQLSSLCA (version 2.04+)
String : OPTIONAL
The path to the file listing the trusted certificate authorities.

MySQLSSLCAPath (version 2.04+)
String : OPTIONAL
The path to the directory containing the PEM-formatted, trusted certificate authorities.

MySQLSSLCert (version 2.04+)
String : OPTIONAL
The path to the MySQL client certificate.

MySQLSSLCipherList (version 2.04+)
String : DEFAULT="!ADH:RC4+RSA:HIGH:MEDIUM:LOW:EXP:+SSLv2:+EXP"
The list of SSL ciphers (in 'openssl ciphers' format) to allow for SSL connections.

MySQLSSLKey (version 2.04+)
String : OPTIONAL
The path to the MySQL client certificate key.

MySQLSocket (version 2.04+)
String : OPTIONAL
The path to the MySQL server socket file (Unix only).

MySQLTableGID
String : OPTIONAL
The table that stores the group memberships. AuthFormMySQLFieldGID and AuthFormPageNotAllowed must also be configured along with the Require directive in a directory container (refer the the Apache2 documentation for more information). Also, the table must have a UID and GID field where the UID field is the primary key.

MySQLTableGIDCondition
String : OPTIONAL
Condition to add to the WHERE-clause when querying the group membership table.

MySQLTableSID
String : DEFAULT="sessions"
The table that stores session records. At minimum, the table should have a SID field and a UID field where the SID field is the primary key.

MySQLTableSIDCondition
String : DEFAULT="sid=$sid AND uid=$uid"
Session validation condition used in the WHERE-clause when querying the session table. The variable placeholders (denoted as $var) store session values passed by the clients and validated by the module. With the exception of the placeholders, the syntax of the condition is the same as the syntax in a MySQL WHERE clause.

MySQLTableTracking
String : OPTIONAL
The table that stores request tracking information. The table must have a field for UID, client's IP address, download date, download path, and download size (no primary keys).

MySQLTableTrackingCondition
String : OPTIONAL
Condition to add to the WHERE-clause when querying the tracking table.

MySQLUsername
String : DEFAULT=<Apache2 Username>
The MySQL user used to connect to the MySQL server.

PageAutoRefresh (version 2.02+)
String : OPTIONAL
The URL to which to auto-refresh. Effectively speaking, this directive defaults to the current page if session expiration is disabled and/or not used (see AuthFormSessionAutoRefresh). Otherwise, this directive defaults to AuthFormPageExpired.

PageExpired
String : OPTIONAL
The URL to the 'session expired' page.

PageLogin
String : REQUIRED
The URL to the page containing the login form.

PageNotAllowed
String : OPTIONAL
The URL to the 'invalid group member' page.

SessionAutoRefresh (version 2.02+)
Number : DEFAULT=-1
How many seconds should the web browser refresh to a certain page (if not the current page). A value of 0 means disable auto-refreshing. A value of -1 (default) means auto-refresh when the client's session expires; if session expiration is disabled, auto-refreshing will effectively be disabled. Any value greater than 0 indicates a fixed number of seconds to auto-refresh. See also AuthFormPageAutoRefresh.

SessionCookies
Flag : DEFAULT="Off"
Whether to use cookies or the URL query string to pass the session keys from the client to the module. ('On' means use cookies; 'Off' means use the URL query string).

SessionDelete (version 2.03+)
Flag : DEFAULT="Off"
Whether or not the module should delete expired sessions per request.
NOTE: This feature is not as robust as managing expired sessions via server-side scripting, especially when auto-refreshing is used.

SessionTimeout
Number : DEFAULT=0
The session inactivity timeout in minutes. A value of '0' indicates no timeout. Also, AuthFormPageExpired must be configured.

TrackingLifetime
Number : DEFAULT=30
Maximum number of days to hold a tracking record. A value of '0' indicates infinite lifetime. (The module goes by the date of download field under the tracking table).


Ideas for Future Releases

Contributing

Anybody who wants to contribute to this project may send me an email at ajarthu@uark.edu. Before doing so, please read through Ideas for Future Releases. When sending source code, either attach a snippet of what's not in the module's source code or a patch. Along with the source code, please include a description in the email message. All source code must be in C. Testers are welcome to send their results (e.g. how many sessions can this module handle, security holes, etc).

Currently, I'm looking for support in obtaining the username and password through HTTP POST and maintaining persistent data in other backends besides MySQL. I'm thinking about adding options to the 'configure' script to specify which backend(s) to compile into the module.

One final note: Let me know if you want me to include your name and/or email address under the contribution list.

Contributors


Copyright 2004-2006 Aaron Arthurs

Licensed under the Apache Lincense, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSES-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Last Updated: Sat Jul 22 12:00:05 CDT 2006