Background:
At work we have a web based administration tool for student accounts, notebook rental and different billing processes. So far it’s been using its own user database for authentication. Since the service personal already has Active Directory accounts and matching group memberships it seems appropriate to use these for authorization and authentification. To make it even simpler we’ll also automatically use the current Windows logon instead of prompting to login (aka Single Sign-On) using Kerberos.

I’ll provide all necessary instructions and hopefully spare some of you some time.

 

Requirements:

This tutorial assumes the following environment:

  • Windows 2008 Active Directory  (Domain: EXAMPLE.COM, Domain Controller: dc01.example.com)
  • Clients: Windows XP or newer
  • Linux Webserver (web.example.com) running Apache 2.2, examples are provided for Ubuntu 10.04 LTS
1) Creating a User Account
First of all you need to create a new user account (not a computer account!) for the webserver in your domain . Since the webserver is called “web” we’ll simply name it kerbweb (feel free to use any other name). Afterwards you’ll need to add the service principal to that account and export the keytab to a file. Kerberos uses this keytab file to authenticate to the domain controller later on.
To create this file open a command shell with administrator privileges (important) on your domain controller  (Start->Run.., type ‘cmd’, right-click command prompt and select Run as Administrator). Execute following command by substituting the placeholders with the correct values:

ktpass /princ HTTP/#full_hostname_of_your_linux_server#@#domain# /mapuser #username#@#domain# /pass #random password# /crypto rc4-hmac-nt /ptype KRB5_NT_SRV_HST /out #filename#.keytab
 For our example it would look like this:
ktpass /princ HTTP/web.example.com@EXAMPLE.COM /mapuser kerbweb@EXAMPLE.COM /pass randompasswordetc /crypto rc4-hmac-nt /ptype KRB5_NT_SRV_HST /out web.keytab
This will create a keytab file with rc4 encryption (using AES is also possible but your linux machine must support it) with the principal name HTTP/web.example.com which is what Apache will use when running on the host web.example.com. Important: A principal name must not be assigned to multiple user accounts! Move this file to your web server. For future reference I’ll assume that you stored it as /etc/apache2/web.keytab but any other location is fine as well.

2) Installing and Configuring Kerberos
Install Kerberos on your linux machine. The process is dependant on your distribution. For Ubuntu use
apt-get install krb5-user
This should install the necessary software and create a configuration file /etc/krb5.conf. Adjust this file to your environment. For our example it should look like this:
[libdefaults]
        default_realm = EXAMPLE.COM
        default_tgs_enctypes = arcfour-hmac-md5 RC4-HMAC DES-CBC-MD5 DES-CBC-CRC
        default_tkt_enctypes = arcfour-hmac-md5 RC4-HMAC DES-CBC-MD5 DES-CBC-CRC

[domain_realm]
        web.example.com = EXAMPLE.COM

[realms]
        EXAMPLE.COM = {
                kdc = dc01.example.com
                admin_server = dc01.example.com
                default_domain = example.com
        }
It is important that you list the above encryption types since we used RC4-HMAC for our keytab file.
Now let’s see if Kerberos itself is able to talk to your domain controller. Run the following command by replacing _username_ with a valid active directory account:
kinit _username_@EXAMPLE
You should be prompted for the user’s password. If everything works fine the command should simple exit (no output). Afterwards run
klist
to list kerberos tickets your server received from the domain controller. A single ticket should appear from our kinit call. If this does not work the kerberos configuration in incorrect. Try to google for the error message you receive.
Now that we’ve got Kerberos working it’s time to test if our keytab file is working correctly. To do this we’ll run kinit again but this time instead of an actual user use the keytab file and the principal name like this:
kinit -k -t /etc/apache2/web.keytab HTTP/web.example.com@EXAMPLE.COM
This should not produce any output if the keytab is working fine. Now run both of these commands:
kvno HTTP/web.example.com@EXAMPLE.COM
klist -e
The output should list two tickets (one for HTTP/web.example.com) with the encryption and the encryption tpye “ArcFour with HMAC/md5, AES-256 CTS mode with 96-bit SHA-1 HMAC”.
Just to make sure, check the encryption type of your keytab with the following command:
klist -e -k /home/cippool/servicebackend.keytab
It should show the same encryption type. If not, something’s wrong with your keytab. Try to rebuild it.

3) Webserver Configuration
Now that we’ve got Kerberos running and are able to talk to the domain controller using our keytab file it’s time to get the web server to use it.
Note: This is a good time to chown the keytab to your webserver user and chmod 0400 it to deny access to anyone else.
To enable Kerberos Authentification in Apache you need to install the mod_auth_kerb module. In Ubuntu run these commands:
apt-get install libapache2-mod-auth-kerb
a2enmod auth_kerb
/etc/init.d/apache2 restart
Apache is now able to authenticate using Kerberos. Time to test this:
Create a new directory in your document root (e.g. /var/www/kerbtest). Make sure your web server allows you to override settings using a .htaccess file by setting  AllowOverride All in your VirtualHost configuration.
Now create a .htaccess file in your new directory with the following content:
AuthName "Kerberos Protected Directory"
AuthType Kerberos
Krb5Keytab /etc/apache2/web.keytab
KrbAuthRealms EXAMPLE.COM
KrbServiceName HTTP
KrbMethodNegotiate on
KrbVerifyKDC on
require valid-user
This will tell Apache that access to this directory is only granted when the current client user is a valid domain account.
Note: Access will be instantly denied if the user is not using a computer that is in our EXAMPLE.COM domain. To offer users a login prompt if they do not belong to the domain (e.g. for home office users) add the line “KrbMethodK5Passwd on”.

4) Webbrowser Configuration
For this to work at all the browser must use a mechanism called SPNEGO.  While this feature is present in most current browsers it usually requires certain settings or conditions. See the next section for instructions on the most common browsers.
Internet Explorer / Google Chrome:
Chrome seems to use a lot of settings from the Internet Explorer on Windows systems. This means if you can get it to work in IE, it’ll also work in Chrome.
Internet Explorer will only use SPNEGO if the URL is trusted and SPNEGO is enabled. The following steps should get you set up and running:

  • Go to Tools -> Internet Options -> Security
  • Select “Local intranet” and click on “Sites” and choose “Advanced”. Add the host name of your web server to the list of local sites (without http://, etc). Click OK to save the settings and return to the Internet Options window.
  • Choose the Advanced tab and scroll down to Security Settings. Make sure that “Enable Integrated Windows Authentication” is checked. Click OK and restart your browser.
Firefox:
In Firefox you are required to add the host name to the list of trusted uris. Unfortunately there is no GUI configuration available for this.
  • Type “about:config” in your address bar
  • Type “network.” in the filter
  • Double-click on network.negotiate-auth.trusted-uris and add the host name. If you need to add multiple host names use a comma  as delimiter
  • Click OK and restart Firefox to activate the setting
5) Testing everything
It’s time to see if the whole ordeal actually works. Add a index.php to the new directory containing just the string “It works” and try to access it using your browser. If you are signed in on a valid domain account, a page with the text should appear, otherwise you should get an access denied error message. If this does not work as expected, read again over all previous steps and look at your apache error log for any clues. If you still can’t get it to work, leave a comment or contact me directly.

6) Getting the user name
While our directory is protected against external access, you’ll usually want to know who exactly is accessing the site. Apache provides that information in the REMOTE_USER environment variable. In PHP you can access this with getenv(“REMOTE_USER”). In our current configuration this will contain “username@EXAMPLE.COM”. Since you already know the domain you can make auth_kerb strip it automatically by adding “KrbLocalUserMapping on” to the .htaccess file (requires a fairly new mod_auth_kerb version though). Afterwards you’ll only receive “username” in getenv(“REMOTE_USER”).

7) Adding Authorization
So far we’ve only covered the Authentication part (“Who is the user?”) which is handled by Kerberos. However most of the time you don’t want any AD account to access a site. Here comes Authorization (“Is the user allowed to do that?”) into play. While it is possible to let the application handle it, it is more convenient to have Apache deny unauthorized users.
A clean approach would be to add all authorized users to a certain active directory group and only allow access to this group.
Create a suitable group in your AD and add a few users. Let’s assume the group is called ‘Webusers’ and is in the organizational unit “Groups”. The Distinguished Name would therefore be “CN=Webusers,OU=Groups,DC=example,DC=com”.
To limit access to certain AD entities, you’ll need an additional Apache module called mod_authnz_ldap.
In Ubuntu this module should already installed and only needs to be enabled:
a2enmod authnz_ldap
/etc/init.d/apache2 restart
Depending on your installation, Apache might need a valid user to access the AD using LDAP. You can try to omit the AuthLDAPBind* lines in the configuration below, but if that does not work, add a new user account. I’ll use “ldapuser” and “ldappass” as username and password for the example. You should obviously use something more secure.
Now we only need to add the required configuration to our .htaccess file. Remove the current “require valid-user” line and instead add:
AuthLDAPURL "ldap://dc01.example.com/dc=example,dc=com?sAMAccountName"
AuthLDAPBindDN ldapuser@example.com
AuthLDAPBindPassword ldappass
Require ldap-group CN=Webusers,OU=Groups,DC=example,DC=com
AuthLDAPURL should be an URI to your domain controller. If you want to use a SSL connection use ldaps:// (this will usually require some additional linux configuration like a certificate). sAMAccountName is the name of the attribute that contains the username. This means Apache will search in your AD using LDAP for the sAMAccountName that Kerberos provided and then make sure it belongs to the group Webusers. You can add multiple Require statements and they will be handled as OR statements (meaning a user must fulfill only one of the requirements, not all), e.g. to add multiple groups or OUs (like Accounting and Management).
Now a user should only be able to access the site if he has a valid domain account, the browser provides SPNEGO and he belongs to the given group.

8) Recap
For reference here’s a short list of the steps we had to do:
  1. Add a new AD user for the web server
  2. Create a keytab file for the user with the correct principal name
  3. Install and configure kerberos on your web server
  4. Configure Apache to use mod_auth_kerb and add the necessary settings to a .htacces file (or directly to your VirtualHost if you prefer)
  5. Add Authorization using LDAP
I hope you found this tutorial helpful. I’m only human and make mistakes, so please point out any errors you encounter.