MySQL based authentication in Apache

I like HTTP. A simple, robust protocol that (in itself) has so many lovely features already if one knows how to use them. As such, I wanted to try and see if I could use the standard HTTP authentication more often for my websites (especially those that I don’t want anyone to access).

Of course, everyone who has ever looked at protecting their phpMyAdmin directory on their website probably came across the standard .htpasswd way of doing things in Apache. However, in my latest server setup, everything is run out of a MySQL database (e.g. email users & addresses for dovecot & postfix, this blog, my webmail, my website …). So I thought: maybe instead of having to constantly maintain .htpasswd files, I could utilize my database to do so. And it works quite nicely!

Prerequisits

  1. mod_auth_mysql from somewhere (build yourself or get a package…)
  2. Load it into your Apache configuration with this or something similiar…
    LoadModule auth_mysql_module /usr/lib/apache2/modules/mod_auth_mysql.so

Setting up the DB

This is my sample setup and not the ultimate truth, so it is possible to change DB name, user, password, tables and all of that (the Apache config shows that later)!

Create a database, user apacheUser and password secretPassword

CREATE DATABASE `apache` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `apache`;
CREATE USER 'apacheUser'@'localhost' IDENTIFIED BY 'secretPassword';
GRANT SELECT ON `apache` . * TO 'apacheUser'@'localhost';

I use a setup with two tables: Users and groups

CREATE TABLE IF NOT EXISTS `apache`.`users` (
 `username` char(100) NOT NULL,
 `passwd` char(100) NOT NULL,
 PRIMARY KEY (`username`)
);
CREATE TABLE IF NOT EXISTS `apache`.`groups` (
 `username` char(100) NOT NULL,
 `group` char(100) NOT NULL,
 PRIMARY KEY (`username`,`group`)
);

And of course, adding a sample user and group

INSERT INTO `apache`.`users` (`username` ,`passwd`)
   VALUES ('csh', MD5( 'secret' ));
INSERT INTO `apache`.`groups` (`username` ,`group`)
   VALUES ('csh', 'testGroup');

Obviously, one could create a foreign key relationship or even a group header table, but that’s too much hassle for the time being… The password column is filled with MD5 hashes of passwords (which is probably insecure, I know, but that was the easiest hash I could find in the configuration).

Setting up a password protection

Now this can go into any .htaccess file or (in my case), I put that in the actual virtual host definition for the hosts I want to protect.

<Directory /http/test> 
   Options none 
   AllowOverride All 
   Order allow,deny 
   Allow from all 
   AuthBasicAuthoritative Off 
   AuthMYSQL on 
   AuthMySQL_Authoritative on 
   AuthMySQL_DB apache 
   Auth_MySQL_Host localhost 
   Auth_MySQL_User apacheUser 
   Auth_MySQL_Password secretPassword
   AuthMySQL_Password_Table users 
   AuthMySQL_Username_Field users.username 
   AuthMySQL_Password_Field users.passwd 
   AuthMySQL_Empty_Passwords off 
   AuthMySQL_Encryption_Types PHP_MD5 
   AuthMySQL_Group_Table "users, groups" 
   AuthMySQL_Group_Clause " AND users.username = groups.username" 
   AuthMySQL_Group_Field groups.group 
   AuthType Basic 
   AuthName "Please log in" 
   Require group testGroup 
</Directory>

Just to point out the obvious, the above Apache configuration will force a user to authenticate against a username in table `users` with a password which (MD5 hashed) equals the string in the passwd column of `users`. Also, there needs to be an entry in `groups` with the username and the group ‘testGroup’, otherwise the user is not allowed either.

The values in bold are obviously things you probably want to change (mostly in accordance with the DB settings/user/pwd created above. The really important bit to figure out here was that AuthMySQL essentially takes these “settings” and just concatenates them into one large SQL statement. It took me a bit of source code browsing to figure out the two table approach described here, and I’m sure one could even go further to split it even more thoroughly.

 

 

 

PHP, JavaScript & AJAX

I’m surely getting old… I remember back in the day when PHP websites were still… well… fully PHP and JavaScript was this little bit of nasty add-on that you didn’t want to do because IE6 would screw it all up 🙂

I’ve recently been doing some PHP&JS work and was playing around with jQuery! What a revelation! Back when I created my CCMS (http://git.mrman.de/ccms), I had to use iframes that would load pure JavaScript to get the “interactive” part done. Life is so much simpler these days, which leads me to the purpose of this post.

I am currently studying for my Systems Architecture Exam and thus am looking at the architectural aspect of things more closely these days. And given my latest web project (http://git.mrman.de/simpleStock) I became quite fond of what I would describe as an API based architecture. It’s probably not new and has a way more fancy name out there, but I wanted to share my 2 cents non-the-less.

The Architecture

In (a/my) traditional PHP setup, every page would be served more or less including PHP coding that read & formatted data from a database or somewhere. This was fine back then, but given the ease that jQuery enables AJAX calls and its powerful front-end possibilities, I have started to move all my PHP backend coding into a single file I call api.php.

Now this one file is obviously not all the logic, but it provides a gateway for all functionality that I want to be able to achieve. Essentially, it redirects the various GET/POST/… requests into a variety of PHP classes that actually do the requested job. In another project, I even went as far as to redirect the resource path into the api.php via apache modules, so that you could call something like /songs/1/tags and get a list of tags for song 1….

All communication in and out of the api.php is done via JSON.

On the front-end, essentially static pages are served (- they are not completely static since I use PHP to include the same menu everywhere but almost- ), and AJAX requests get the data via the api.php interface.

Pros and Cons

This allows the following (in my opinion really cool) things:

  1. Beautiful View vs. Model abstraction with a little controller on both sides of the infrastructure
  2. Utilizing HTTP the way God (or Roy Fielding) intended it to be. Error codes on errors, PUT, POST, GET, DELETE requests against resources, the whole shebang
  3. This is really easy to test (manually & automatically)!
  4. Re-usability for other applications
  5. Cleaner code
  6. Less data transfer
  7. One can switch away from PHP easily 🙂

Of course there are disadvantages, the biggest being that the browser needs JavaScript and the speed and performance to be able to handle it.

Also, the api.php will stand by itself, therefore the design needs to anticipate all kind of inputs and make sure they are handled gracefully. However, I consider this actually and advantage since it makes for clean and robust code!

Things I haven’t properly tried yet

  • Authentication. So far I have used the standard Apache authentication module (actually, the mysql backed one – another blog post is to follow about that), but I would need to see how this plays out with the API and different access levels. However, I think it can be done and it would actually mean that the system would follow overall HTTP authentication rather than a PHP specific one which again, is AWESOME!
  • I would like to see how this thing scales in a larger environment. It would probably be pretty good, given that the front-end is essentially static (so you could almost use a CDN) and only the api.php hits the server
  • This is not directly related to this architecture, but more general. I’d like to try and introduce proper locking mechanisms in a stateless world. Not sure how to go about this yet (read a couple of promising approaches though), so stay tuned 🙂

Anyway, I better get back to studying!