Apache MS Active Directory Auth

I know there are plenty of methods to apache auth through active directory, but recently I found out that some of them didn\’t work for me or didn\’t do well. The more or less successfull one was perl Apache2::AuthenNTLM, but when you have a lot of users, this one blocks apache now and then and causes some real problems.

Like always, found out about apache mod_authnz_external and ended up writing my own authentication script. Here is how to make things work:

First of all download and install mod_authnz_external (google for the package and installation instructions).

Then put the next script somewhere on the apache server (for example /etc/httpd/conf/ad_login.php):

< ?php

// AD server IP address
$ldap_host = \"10.10.10.1\";

// AD Base
$ldap_base = \"dc=example,dc=com\";

// AD domain
$ldap_domain = \"example.com\";

// Connect to AD server
$stderr = fopen(\"php://stderr\",\"w\");
$ldap = @ldap_connect($ldap_host);
if (!$ldap) {
	fwrite($stderr,\"AD Auth: Failed to connect to $ldap_host\\n\");
	fclose($stderr);
	exit(1);
}
@ldap_set_option($ldap, LDAP_OPT_PROTOCOLO_VERSION, 3);
@ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

// Try to login with the supplied username and password 
// (using environment to pass the stuff)
if (!@ldap_bind($ldap,$_ENV[\'USER\'] . \'@\' . $ldap_domain,$_ENV[\'PASS\'])) {
	fwrite($stderr,\"AD Auth: Failed to authenticate \" . $_ENV[\'USER\'] . \"\\n\");
	fclose($stderr);

	// if failed - exit with 1
	exit(1);
}

ldap_unbind($ldap);
fclose($stderr);

// exit with 0 on success
exit(0);

?>

Next, add the following into VirtualHost (or similar) definition in apache config:

AddExternalAuth ad \"/usr/bin/php -f /etc/httpd/conf/ad_login.php\"
SetExternalAuthMethod ad environment

# This can go into Location or Directory sections
AuthType basic
AuthName \"My Closed Zone\"
AuthBasicProvider external
AuthExternal \"ad\"
require valid-user

Restart apache and you are done.

How does it work? Simple. Each time apache will need to authenticate a user, it will start a script (ad_login.php) and pass it username and password as environment variables. The script, in turn, will try to connect to AD and authenticate itself as given user. If that fails – login fails, otherwise – login ok. So basically, if a user has writes to connect to AD, (s)he has write to login to apache.

And of course you can extend the php script with some extras, like additional checks on username, caching and so on.