Active Directory and Apache Kerberos authentication
by Michele Baldessari
This article uses Windows 2003R3 as a KDC, but the exact same setup works with Windows 2008 SP1. The only requirement in case of Windows 2008 is a sufficiently recent Samba installation. In my case, samba 3.4.0-pre1 has been used in both 2003 and 2008 environments.
Introduction
In this short tutorial we’ll set up Kerberos and Apache in a Windows 2003 Active Directory forest. It is required that you know your way around with Debian, Apache configuration and not much more
Initial setup
In this article I’ll explore how to set up an Apache web server on a Linux Debian box (squeeze testing as of 05/2009) with kerberos authentication integrated with Active Directory on Windows 2003R2. The domain name that I used for this test is: int.test. Three machines make up this small lab:
- Domain Controller and Kerberos KDC – Windows Server 2003R2 – pdc.int.test (172.16.11.12)
- Web Server – Debian Squeeze (as of 05/2009) – www.int.test (172.16.11.16)
- Client1 – Windows XP Professional – client1.int.test (172.16.11.252)
I’ll assume that AD is already set up on pdc.int.test and that all the clients and the web server point to it as their DNS server. The first necessary step is to have the DNS zone and the corresponding reverse zone in place:

Once all the DNS business is taken care of (do not forget the reverse PTR pointers), the web server needs to be properly configured, starting with the installation of all the needed packages:
www:~# apt-get install apache2-mpm-prefork libapache2-mod-auth-kerb krb5-config krb5-clients krb5-user samba-client openntpd
NTP
Let’s make sure that the clocks between the webserver and the DC are in sync. Edit /etc/openntpd/ntpd.conf and verify that there is a single line containing the DC as ntp server: server pdc.int.test. Check in /var/log/syslog that the synchronization took place [1] :
May 8 22:46:38 www ntpd[3422]: peer 172.16.11.152 now valid
May 8 22:47:59 www ntpd[3422]: clock is now synced
Kerberos
Once time synchronization is taken care of (Kerberos is very sensible about reliable and synchronized clocks), we need to join the machine to the new Active Directory. First let’s configure the underlying kerberos libraries in /etc/krb5.conf:
[libdefaults]
default_realm = INT.TEST
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true
fcc-mit-ticketflags = true
default_keytab_name = FILE:/etc/krb5.keytab
[realms]
int.test = {
kdc = pdc.int.test
master_kdc = pdc.int.test
admin_server = pdc.int.test
default_domain = int.test
}
[domain_realm]
.int.test = INT.TEST
int.test = INT.TEST
If everything is set up correctly, you should be able to authenticate to AD via kerberos:
www:~# kinit Administrator
Password for Administrator@INT.TEST:
Double-check that your TGT is correctly set up:
www:~# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: Administrator@INT.TEST
Valid starting Expires Service principal
05/08/09 22:57:48 05/09/09 08:57:52 krbtgt/INT.TEST@INT.TEST
renew until 05/09/09 22:57:48
Samba
Once Kerberos is in place we’ll configure samba. The file /etc/samba/smb.conf should contain the following:
netbios name = www realm = INT.TEST security = ADS encrypt passwords = yes password server = pdc.int.test workgroup = INT
Let’s join the domain [2]:
www:~# net ads join -U Administrator
Using short domain name -- INTTEST
Joined 'WWW' to realm 'int.test'
Keytab
Now that most of the groundwork is done and the web server joined the AD domain correctly, we need to get the service keys in a keytab to be used by apache. Note that most tutorials suggest to use ktpass.exe on windows. I find this approach much more complex and error-prone (i.e. something like ktpass -princ HTTP/www.int.test@INT.TEST -mapuser http-linux-server -crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL -mapop set +desonly -pass password -out c:\server.keytab then copying the file to the linux box, etc.).
Thanks to samba this can be easier:
www:~# net ads keytab add HTTP -U administrator
Processing principals to add...
Enter administrator's password:
Now in /etc/krb5.keytab there are the service principals for HTTP/www.int.test. In order to verify it you can use the ktutil tool:
www:~# ktutil
ktutil: rkt /etc/krb5.keytab
ktutil: l
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1 19 HTTP/www.int.test@INT.TEST
2 19 HTTP/www.int.test@INT.TEST
3 19 HTTP/www.int.test@INT.TEST
4 19 HTTP/www@INT.TEST
5 19 HTTP/www@INT.TEST
6 19 HTTP/www@INT.TEST
We also need to give permission to apache to read this keytab file:
www:~# chmod 740 /etc/krb5.keytab
www:~# chgrp www-data /etc/krb5.keytab
It’s important to understand that the above solution only makes sense if apache is the only kerberized service. If more than apache is present it makes sense to have separated keytabs with appropriate permissions.
Apache
Make sure the mod_auth_kerb module is active with a2enmod auth_kerb.
<Location /secured> AuthType Kerberos AuthName Kerberos Login KrbMethodNegotiate On KrbMethodK5Passwd On KrbAuthRealms INT.TEST Krb5KeyTab /etc/krb5.keytab require valid-user </Location>
Make sure that the relative dir secured exists and that it contains an ad hoc index.html so we can verify the successful authentication. Once the testing phase is completed, I tipically switch off the KrbMethodK5Passwd option, so users do not get promptet for authentication if for some reason the Kerberos authentication fails.
Set up the client
On the Windows XP Pro client (client1.int.test) we can test this kerberized Apache setup.
Firefox
Mozilla Firefox is a bit simpler to set up. You need to add the domain int.test to the options network.negotiate-auth.trusted-uris and network.negotiate-auth.delegation-uris.

Once this is done, we just need to browse to the page where Kerberos authentication is forced: www.int.test/secured

Internet Explorer 8
Internet Explorer is a little bit more difficult to setup. With this I mean that there are a few more spots where things can go wrong. First you need to go in Tools, Internet Options, Advanced and all the way to the bottom you need to make sure that Enable Integrates Windows Authentication is active (it might require a restart):

You will also need to add *.int.test to the Intranet Zones. (Note that Integrated Windows Authentication does not work on home variants of Microsoft Operating Systems)
Under Tools, Internet Options, Security, Custom Level verify that Automatic logon only in Intranet zone is selected.
Once all these steps are taken care of you’ll see the same HTML page as Firefox when going to http://www.int.test/secured
Footnotes
[1] You should make sure that the Domain Controller that has the PDC Emulator role in your domain synchronizes the time with an NTP box somewhere on the net or via a special time HW device.
[2] If you encounter a GSS error related to Stream modified, it might be due to a bug in the kerberos 1.7beta libs (It’s been fixed in beta3)
Hi Burton,
I’d need the exact domain and forest level. Then I’ll try to setup something similar
cheers,
Michele
Hi Anbarasu,
I am not too familiar with Solaris. If the SSO you are speaking about is for Windows Clients to access the samba server on solaris without reentering the passwords, then I’d be surprised if it didn’t work.
But again I am not very big on that Operating System
cheers,
Michele
Michele –
the Domain and Forest are both running in Windows Server 2003 mode.
thanks,
B
Hi,
I’m still concern about the permission of /etc/krb5.keytab. for security reasons, it should only be readable by root. Then other thing is if we keep separate ‘keytab’ files, it then causes the issue of service principal expiration.
Do you have any workaround or has Apache Kerberos module addressed this?
Thanks.
T
Not sure I exactly get your question here
Hi Michele,
I’ve been trying to set up SSO for customer in a intranet otrs install (on a ubuntu 12.04 server). users use win 7 clients and AD is on a 2008 server.
Everything seems to work (the kerberos tools or net ads commands) but either on IE or Firefox, users are asked for domain ids on the index page (customer.pl). After filling in the id, page is forwarded to the logged on otrs page so authentication is actually done and OTRS log in seems bypassed (but that’s just replacing one log with another).
The thing is there is no ticket creation when a user log with a win7 client, and same, if i create manually a ticket using kinit, ticket doesn’t get used when going to the otrs page. Do you know what is the cause of that ?
Best regards
Hi there,
mmh hard to say. Can you increase the apache logs to DEBUG and see what’s going there? Also a network trace would help.
Also I’m not sure I understand what you mean with “no ticket creation when a user logs in with a win7 client”, can you expand?
cheers,
Michele
[...] http://arthurdejong.org/nss-pam-ldapd/nslcd.conf.5 http://arthurdejong.org/nss-pam-ldapd/nslcd.8 http://acksyn.org/?p=460 This entry was posted in Uncategorized. Bookmark the permalink. ← Olá [...]
Hi Michele.
Very good guide
But what to do when you have a VirtualHost or multiple VirtuelHosts?
Server is called: server01 and webpage is test.example.com and hello.example.com
Thanks for your time
Hi Daniel,
Virtual Hosts work without big problems with one caveat:
vhost1
Krb5KeyTab /etc/httpd/keytabs/default
KrbServiceName HTTP/vhost1.example.org
vhost2
Krb5KeyTab /etc/httpd/keytabs/default
KrbServiceName HTTP/vhost2.example.org
In the above scenario (multiple vhosts and one keytab file) you need to use CNAMEs in DNS for the vhosts.
If you want split keytab files per vhost you will need A records for your vhosts
hth,
Michele
Awesome doc. A note on the virtuals above. When I try this, the site in the default works just fine (hostname.domain.com) but when I create other virtuals where hostname isn’t the actual machine name but a CNAME in DNS I get the following error:
[Sat Aug 18 12:47:53 2012] [debug] src/mod_auth_kerb.c(1628): [client 192.168.10.115] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Sat Aug 18 12:47:53 2012] [debug] src/mod_auth_kerb.c(1628): [client 192.168.10.115] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Sat Aug 18 12:47:53 2012] [debug] src/mod_auth_kerb.c(1240): [client 192.168.10.115] Acquiring creds for HTTP/www.office.mytestdomain.com
[Sat Aug 18 12:47:53 2012] [debug] src/mod_auth_kerb.c(1101): [client 192.168.10.115] GSS-API major_status:000d0000, minor_status:000186a4
[Sat Aug 18 12:47:53 2012] [error] [client 192.168.10.115] gss_acquire_cred() failed: Unspecified GSS failure. Minor code may provide more information (, )
Is there something else I need to do other than just add the virtual host configuration to apache? I pointed the virtual host entry to the same keytab as you mentioned above but is there anything else?
Hello Michele;
I read your instructions, along with many others, when setting up a redhat web server that needed to authenticate via AD. I agree with you that using the “net ads keytab add HTTP -U administrator” route appears easier that using ktpass on windows, so that is exactly what I did. When the Kerberos setup was complete, the server accepted the user’s tickets for integrated authentication perfectly.
However, I had an emergency come up and I had to put away the apache implementation for two months. I was then quite surprised when I got back to it two days ago, because it no longer authenticated users. Nothing had changed on the RedHat server. But the logs apache verified it had worked in mid June, but not today. I suspected something in AD had changed.
So, after two days of sleuthing, it turns out I was correct, something had changed in AD. It appears that AD renegotiates the computer account passwords on a regular basis. The password invocation number is the same thing as the KVNO stored in the keytab and reported by the klist and kutil utilities. Unfortunately, the “net ads keytab add HTTP -U administrator” is a samba utility and it uses the computer account in AD to hold Service Principal Names. It also populates the KVNO in the keytab with the current computer account password change number. So, everything will work fine up until AD negotiates a new password with Samba, at which point the KVNO numbers in the keytab will no longer be accurate, and authentication will cease to function.
The solution, unfortunately, is to use the ktpass utility on a windows domain controller to create the SPNs on a dummy AD account. Once the initial SPN is populated in the keytab, one can move it to a linux system and use ktutil to add extra SPNs for alternate web server names. Of course adding extra SPNs to the keytab must be matched by extra SPNs added to the dummy account; the setspn windows utlility can be used to add or delete SPNs on the fly.
By the way, the dummy AD account also needs to have “Password Never Expires” and “User cannot change Password” options set. If the password ever changes, even to the same value, the KVNOs from the keytab will not match the password change number and Kerberos auth will not work. Oh, one other thing, there is a windows utility that will let you check the KVNO (password iteration number) from the windows system:
C\:> ldifde -f spn_out.txt -d “DC=,DC=,DC=” -l *,msDS-KeyVersionNumber -r “(serviceprincipalname=HTTP/*)” -p subtree
The KeyVersionNumber must be the same as the KVNO in the keytab.
Hope this helps! Let me know if you want the full list of how I did this.
Dale
Just a note: Win7 does not allow DES by default, so on the clients you must enable it separately, see http://technet.microsoft.com/en-us/library/dd560670%28v=ws.10%29.aspx
Hi Jason,
usually this should be enough to get it working. I’d need more details (conf, dns entries, apache+mod auth kerb versions and client infos) to speculate more
cheers,
Michele
[...] Michele’s blog » Active Directory and Apache Kerberos authentication – August 31st ( tags: AD activedirectory kerberos authentication apache setup howto tutorial guide ) [...]
Great guide!
In my scenario, I got the following error message while trying the “net ads join”:
[2012/09/18 13:59:13.797077, 0] libads/sasl.c:822(ads_sasl_spnego_bind)
kinit succeeded but ads_sasl_spnego_krb5_bind failed: Strong(er) authentication required
Failed to join domain: failed to connect to AD: Strong(er) authentication required
This was, fortunately, easily resolved by adding the following global configuration option to smb.conf:
client ldap sasl wrapping = sign
Regards,
Johan
Hi Johan,
thanks for the info. Will be handy for quite a few people methinks
cheers,
Michele
Hi Michele, looks like the links to your images are broken…
Hi Donnie,
ups. Thanks for letting me know. I fixed it now.
cheers,
Michele
> chmod 740 /etc/krb5.keytab
Should this not be chmod 640 instead? The file does not need to be executable.
Hi,
I have the same error like Jason:
GSS-API major_status:000d0000, minor_status:000186a4
I have two keytabs. With the first one my apache2 authenticates to the AD, but with the second one it does not.
If I list with klist, both of them contains the same entries.
Please help me how to find the difference between the two keytab files, why my apache2 works only with one of them?
Thank you for your help!
Regards,
Andor
Sorry, I am clearing, my error code is this: minor_status: 000186a9
Log:
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1628): [client 10.0.1.10] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Fri Mar 29 23:24:41 2013] [debug] mod_deflate.c(615): [client 10.0.1.10] Zlib: Compressed 484 to 325 : URL /cgi-bin/test.cgi
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1628): [client 10.0.1.10] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1240): [client 10.0.1.10] Acquiring creds for HTTP@ubuntu.demo.local
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1385): [client 10.0.1.10] Verifying client data using KRB5 GSS-API
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1401): [client 10.0.1.10] Client didn’t delegate us their credential
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1420): [client 10.0.1.10] GSS-API token of length 9 bytes will be sent back
[Fri Mar 29 23:24:41 2013] [debug] src/mod_auth_kerb.c(1101): [client 10.0.1.10] GSS-API major_status:000d0000, minor_status:000186a9
[Fri Mar 29 23:24:41 2013] [error] [client 10.0.1.10] gss_accept_sec_context() failed: Unspecified GSS failure. Minor code may provide more information (, )
[Fri Mar 29 23:24:41 2013] [debug] mod_deflate.c(615): [client 10.0.1.10] Zlib: Compressed 484 to 325 : URL /cgi-bin/test.cgi
I reinstalled my linux and I did all the steps than on the other linux, SSO works.
It is mysterious.