Webtatic.com

Just another technical blog

Webtatic::AuthDBI

A mod_perl module (mod_perl v2 and Apache httpd v2.2) for basic and digest HTTP authentication using a DBI backend.

This module is similar to mod_auth_mysql, but is written for mod_perl, and includes the much more secure Digest Authentication.

Whilst not as secure as a HTTPS connection, digest authentication does not transmit the plaintext password over the internet to the server. It also has features that help prevent replay attacks.

The digest implementation in Webtatic:AuthDBI uses mod_auth_digest to generate and check the digest nonce, along with additional features with quality of protection (qop) auth.

A digest must be created from the user name, realm and password and stored in the AuthDBI_DigestField field in the table. Alternatively you can set AuthDBI_PwEncryption plain, and it will look for the plaintext password in the field corrisponding to AuthDBI_PasswordField.

A digest is formed via the following:

digest = MD5(username . ‘:’ . realm . ‘:’ . password)

Without qop, the module performs the following check on a pregenerated digest stored in the database (or alternatively if the password is stored plaintext, it will generate the digest as well):

MD5(digest . ‘:’ . nonce . ‘:’ . md5(requestMethod . ‘:’ . requestUri)) == response

Or if qop=auth:

MD5(digest . ‘:’ . nonce . ‘:’ . nonce_count . ‘:’ . clientNonce . ‘:’ . md5(requestMethod . ‘:’ . requestUri)) == response

Download

Webtatic-AuthDBI-0.03.tar.gz

Installation

You will need mod_perl, httpd-devel and apr-devel before installation. (yum install mod_perl httpd-devel apr-devel)

tar zxvf Webtatic-AuthDBI-0.01.tar.gz
cd Webtatic-AuthDBI-0.01/
perl Makefile.PL
make install

Use

Create a database “auth”, and add the table:

CREATE TABLE `user_info` (
  `user_name` varchar(25) NOT NULL,
  `user_password` varchar(32) NOT NULL,
  `user_digest` varchar(32) NOT NULL,
  `user_group` varchar(25) NOT NULL,
  `enabled` tinyint(3) UNSIGNED NOT NULL,
  PRIMARY KEY  (`user_name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Grant a mysql user access to the database:

GRANT SELECT ON `auth`.`user_info` TO 'auth_user'@'localhost' IDENTIFIED BY 'auth_password';

Add a user to the table:

INSERT INTO `auth`.`user_info` (user_name, user_password, user_digest, user_group, enabled) VALUES
('myuser', MD5('mypassword'), MD5(CONCAT('myuser',':','My Realm', ':', 'mypassword')), 'mygroup', 1);

Inside your Apache conf, or alternatively inside a .htaccess file (remove the <Location /> tag)

<Location "/admin/">
PerlLoadModule Webtatic::AuthDBI
AuthDBI On
AuthDBI_DSN dbi:mysql:auth:localhost:3306
AuthDBI_User auth_user
AuthDBI_Password auth_password
 
AuthDBI_UserTable user_info
AuthDBI_NameField user_name
AuthDBI_DigestField user_digest
AuthDBI_GroupField user_group
AuthDBI_UserCondition "`enabled` = 1"
 
AuthType Digest
AuthName My Realm
 
require group mygroup
</Location>

Configuration

AuthDBI Directive

Description: Enables/disables authentication using the module
Syntax: AuthDBI on|off
Default: AuthDBI off
Context: server config, virtual host, directory, .htaccess

AuthDBI_DSN Directive

Description: User for DBI to connect to database server on
Syntax: AuthDBI_DSN dbi:type:host:database:port
Default: AuthDBI_DSN dbi:mysql:localhost:auth:3306
Context: server config, virtual host, directory, .htaccess

AuthDBI_User Directive

Description: User for DBI to connect to database server on
Syntax: AuthDBI_User username
Default: <not defined>
Context: server config, virtual host, directory, .htaccess

AuthDBI_Password Directive

Description: User for DBI to connect to database server on
Syntax: AuthDBI_Password password
Default: <not defined>
Context: server config, virtual host, directory, .htaccess

AuthDBI_Authoritative Directive

Description: Specifies whether to check other auth providers if no matches
Syntax: AuthDBI_Authoritative On|Off
Default: AuthDBI_Authoritative On
Context: server config, virtual host, directory, .htaccess

AuthDBI_UserTable Directive

Description: Table from which to validate the user name and password
Syntax: AuthDBI_UserTable table
Default: AuthDBI_UserTable user_info
Context: server config, virtual host, directory, .htaccess

AuthDBI_UserCondition Directive

Description: Additional conditions on which to match the user
Syntax: AuthDBI_UserCondition conditions
Default: <not set>
Context: server config, virtual host, directory, .htaccess

This directive supports formatting with request variables:

%h - Remote hostname
%a - Remote IP
%f - Filename
%V - Apache ServerName
%v - HTTP Host
%H - Protocol (e.g. HTTP/1.1)
%m - Request method (e.g. GET)
%q - Query string
%r - Request line (e.g. GET /admin/)
%U - Request Uri (not including query string)
%% - Prints %
%{VAR}C - Cookie VAR
%{VAR}e - Environmental variable VAR
%{VAR}n - Apache note VAR
%{VAR}i - Request header VAR

e.g. AuthDBI_GroupCondition “remote_ip = ‘%a’”

AuthDBI_NameField Directive

Description: Field name from which to match the user name
Syntax: AuthDBI_NameField field
Default: AuthDBI_NameField user_name
Context: server config, virtual host, directory, .htaccess

AuthDBI_PasswordField Directive

Description: Field name from which to match the password
Syntax: AuthDBI_PasswordField field
Default: AuthDBI_PasswordField user_password
Context: server config, virtual host, directory, .htaccess

AuthDBI_PwEncryption Directive

Description: Encryption scheme from which the password was encoded
Syntax: AuthDBI_PwEncryption plain|md5|crypt
Default: AuthDBI_PwEncryption md5
Context: server config, virtual host, directory, .htaccess

Set this to plain if prestoring a digest from the username:realm:password is not viable and there is a plaintext password in the AuthDBI_PasswordField column.

AuthDBI_DigestField Directive

Description: Field name from which to use as the digest in AuthType Digest mode when AuthDBI_PwEncryption is md5
Syntax: AuthDBI_DigestField field
Default: AuthDBI_DigestField user_digest
Context: server config, virtual host, directory, .htaccess

AuthDBI_GroupTable Directive

Description: Table from which to authorize using Require group …
Syntax: AuthDBI_GroupTable table
Default: whatever AuthDBI_UserTable is set to
Context: server config, virtual host, directory, .htaccess

AuthDBI_GroupCondition Directive

Description: Additional conditions on which to match the users’ groups
Syntax: AuthDBI_UserCondition conditions
Default: <not set>
Context: server config, virtual host, directory, .htaccess

See AuthDBI_UserCondition for formatting details

AuthDBI_GroupField Directive

Description: Field name from which to get the user’s group(s)
Syntax: AuthDBI_GroupField field
Default: AuthDBI_GroupField user_group
Context: server config, virtual host, directory, .htaccess

AuthDBI_CacheLifetime Directive

Description: Lifetime of cache entries, zero to disable cache
Syntax: AuthDBI_CacheLifetime seconds
Default: AuthDBI_CacheLifetime 0
Context: server config, virtual host, directory, .htaccess

AuthDBI_CacheDSN Directive

Description: User for DBI to connect to cache database server on
Syntax: AuthDBI_DSN dbi:type:host:database:port
Default: AuthDBI_DSN dbi:mysql:localhost:auth:3306
Context: server config, virtual host, directory, .htaccess

AuthDBI_CacheTable Directive

Description: Table from which to validate the user name and password
Syntax: AuthDBI_CacheTable table
Default: AuthDBI_CacheTable user_cache
Context: server config, virtual host, directory, .htaccess

Example cache table:

CREATE TABLE IF NOT EXISTS `user_cache` (
  `user_name` varchar(255) NOT NULL,
  `user_password` varchar(255) NOT NULL,
  `user_realm` varchar(255) NOT NULL,
  `user_timestamp` bigint(20) UNSIGNED NOT NULL,
  PRIMARY KEY  (`user_name`,`user_realm`)
) ENGINE=MEMORY;