Kerberos auth with Apache/PHP

Robert AndresenProgramming, Tutorials 6 Comments

We have a portal/intranet-webpage at my work, running with Apache, PHP and MySQL. In 2011, a colleague and me sat 16 hours (without a break) and configured kerberos authentication with the Linux webserver.

Now in 2015 we needed kerberos with a new webserver. We did write a doc back in 2011, but when you sit for 16 hours – the doc can be a little short of all the things we actually did. The configuration took about 8 hours this time, and now I’m updating the doc and blogging it here.

2019-03: The format on this article has been updated. Please make sure to check any code for wierd characters, before you blindly copy and paste 🙂

Why

When users log in on their Windows computers, they can access the Intranet-webpage without having to authenticate themselves one more time.

Prerequisite:

  • A working domain with basic knowledge of it.
  • A working Linux webserver with Apache and PHP

My setup:

  • CentOS 7 (With Apache 2 and PHP 5.4)
  • Domain controller on Windows server 2008 R2.

Before you start:

The commands and images are masked from all that are related to my work-infrastructure. Remember to change it matching your own network and domain. Contoso.com is the example domain and http://website.contoso.com is the website DNS. Use the images for illustration for what the output should look like.

$vi   is the editor used in this guide. Use the editor of your own choice. To edit a file in vi, enter a-key when you are in the file and start editing. When your done, press esc and just write :wq (write quit) to save (or :q to quit).

I wrote this guide as I configured kerberos – which means I didn’t necessary follow the steps below in the same order. I got some error messages that probably was because of the last kerberos configuration.

I recommend scrolling through this guide and the sources at the bottom BEFORE you start, to get a better view of what you are going to do. If your not at work, go get some beers, because this could take some time 🙂

As kerberos already was in use on other services in my case, I am not sure if any changes need to be made at the domain-structure.

1. Turn OFF SELinux and firewall

Do this under setup to prevent any interupt, and remember to set them back when you’re done!

$ setenforce 0
$ systemctl stop firewalld

2. Install mod_auth_kerb

You need the mod_auth_kerb module for apache, so apache can handle the kerberos tickets.

$ yum install mod_auth_kerb
$ systemctl restart httpd.service

3. Join the Linux server into the domain

Source: http://www.hexblot.com/blog/centos-7-active-directory-and-samba

Install required packages:

$ yum install realmd samba samba-common oddjob oddjob-mkhomedir sssd ntpdate ntp

3.1 Sync time with the domain

This is not required, but the time have to match the domain controller in order to authenticate users.

$ systemctl enable ntpd.service
$ ntpdate domaincontroller-01.contoso.com
$ systemctl start ntpd.service

3.2 Join the domain

$ realm join --user=adminuser@contoso.com contoso.com

List the domain-data for the server to check if it works. This looked fine to me the first time, but the computer object did not show in AD. So I had to leave ($realm leave…) the domain and join it one more time for some reason.

$ realm list

$ realm list
mydomain.local
type: kerberos
realm-name: CONTOSO.COM
domain-name: mydomain.local
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: oddjob
required-package: oddjob-mkhomedir
required-package: sssd
required-package: adcli
required-package: samba-common
login-formats: %U@mydomain.local
login-policy: allow-realm-logins

3.3 Samba config

$ vi /etc/samba/smb.conf

The config should already be something like this. This is my config-file:

#======================= Global Settings  ====================================

[ global ]
#--authconfig--start-line--

# Generated by authconfig on 2015/01/13 17:14:47
# DO NOT EDIT THIS SECTION (delimited by --start-line--/--end-line--)
# Any modification may be deleted or altered by authconfig in future

password server = domaincontroller-01.contoso.com
security = domain
idmap config * : range = 16777216-33554431
kerberos method = secrets only
winbind use default domain = false
winbind offline logon = true

#--authconfig--end-line--

4. Computerobject in AD

Open AD and check that the computer object is created.

View the properties for the computer object and go to Delegation tab – make sure that «Trust this computer for delegation to any service (Kerberos only)» is checked.

kerberos_computerobject_delegation

5. Create a service user

Create a service user in the domain.

After the user is created and you run the ktpass in the next step – it would show a new tab named «Delegation» in the user-properties.

kerberos_mgmt_account

6. Generate keytab file

Keytab-file need be created in CMD on a server in the domain. The <USERNAME> should be the service user you created in last step.

Notice: The user will store a key version number. In my case, I created the keytab file on the same user as last time, meaning that the old kerberos setup stopped working.

ktpass -princ HTTP/contoso.com@CONTOSO.COM -mapuser CONTOSO\<USERNAME> -crypto all -ptype KRB5_NT_PRINCIPAL -pass <PASSWORD> -out webpage.HTTP.keytab

Output:

Targeting domain controller: domaincontroller-01.contoso.com
Successfully mapped HTTP/webpage.contoso.com to <username>.
Password succesfully set!
Key created.
Key created.
Key created.
Key created.
Key created.
Output keytab to webpage.HTTP.keytab:
Keytab version: 0x502
keysize 87 HTTP/webpage.contoso.com@CONTOSO.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 26 etype 0x1 (DES-CBC-CRC) keylength 8 (0x404398) keysize 87 HTTP/webpage.contoso.com@CONTOSO.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 26 etype 0x3 (DES-CBC-MD5) keylength 8 (04043 98) keysize 95 HTTP/webpage.contoso.com@CONTOSO.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 26 etype 0x17 (RC4-HMAC) keylength 16 (0x72827cb052e8) keysize 111 HTTP/webpage.contoso.com@CONTOSO.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 26 etype 0x12 (AES256-SHA1) keylength 32 (0x75f60e)keysize 95 HTTP/webpage.contoso.com@CONTOSO.COM ptype 1(KRB5_NT_PRINCIPAL) vno 26 etype 0x11 (AES128-SHA1) keylength 16 (0xf4e248)
kerberos_ktpass

Open the service-user properties. Go to the Delegation tab and make sure the «Trust this user for delegation to any service (Kerberos only) is checked.

kerberos_mgmt_account_delegation

7. Copy keytab file to the webserver

Use WinSCP, mount a NFS or something to copy the generated keytab file to /etc/httpd/conf on the webserver.

7.1 Change the user-rights and group on the keytab-file

chgrp apache webpage.HTTP.keytab
chmod 740 webpage.HTTP.keytab

8. Setspn

Open powershell on a domain controller and add set spn:

PS C:\Users\admin> setspn -s HTTP/webpage.contoso.com <SERVICE USER>
kerberos_setspn

In my case the domain webpage.contoso.com existed from before, so I got a duplicate message. I had to write «PS C:\Users\admin> setspn -D http/intranett.contoso.com <OLD SERVICE USER>» to delete it.

9. Edit /etc/krb5.conf

[logging]
default = /var/log/krb5libs.log
kdc = /var/log/krb5kdc.log
admin_server = /var/log/kadmind.log

[libdefaults]
default_realm = CONTOSO.COM
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
forwardable = yes

[realms]
CONTOSO.COM = {
kdc = domaincontroller-01.contoso.com:88
kdc = domaincontroller-02.contoso.com:88
kdc = domaincontroller-03.contoso.com:88
admin_server = domaincontroller-01.contoso.com:749
default_domain = contoso.com
}

[domain_realm]
webpage.contoso.com = CONTOSO.COM
.contoso.com = CONTOSO.COM
contoso.com = CONTOSO.COM

[appdefaults]
pam = {
debug = true
ticket_lifetime = 36000
renew_lifetime = 36000
forwardable = true
krb4_convert = false
}

 

10. Create a auth folder on your webserver for testing

$ mkdir /var/www/html/auth

Than create a .htaccess file in the folder where you want to authenticate the user. You can also add these parameters at the virtual host config if you want.

$ vi /var/www/html/auth/.htaccess

Insert the following config

AuthType Kerberos
AuthName "Kerberos Login"
KrbServiceName HTTP
KrbMethodNegotiate On
KrbMethodK5Passwd Off
KrbSaveCredentials Off
KrbVerifyKDC On
KrbAuthRealms CONTOSO.COM
Krb5KeyTab /etc/httpd/conf/webpage.HTTP.keytab
require valid-user

Remember to check if Apache loads .htaccess files. See 14.1.

11. Test the kerberos authentication

Create a test folder called auth in www-root.

# mkdir /var/www/html/auth

Create a index.php in the folder:

# vi /var/www/html/auth/index.php

Add the following code to the index.php file:

<?php
echo "<h2>Kerberos Auth</h2>";
echo "Auth type: " . $_SERVER['AUTH_TYPE'] . "<br />";
echo "Remote user: " . $_SERVER['REMOTE_USER'] . "<br />";
?>

 

12. Test website

The page should look like this:

kerberos_chrome_auth_success

13. Turn ON SELinux and firewall

$ setenforce 1
$&nbsp;systemctl start&nbsp;firewalld

14. Troubleshoot

14.1 Enable .htaccess to be read in Apache

If .htaccess isn’t loaded, you need to edit /etc/httpd/httpd.conf and set AllowOverride All.

<Directory "/var/www">
AllowOverride All
# Allow open access:
Require all granted
</Directory>

14.2 Set apache LogLevel to debug

To get all possible messages for debugging, it can be useful to set apache LogLevel to debug. Edit the /etc/httpd/httpd.conf file.

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel debug

14.3 Test keytab file and kerberos authentication

You can test the kerberos authentication from the terminal. First you need to install the kerberos-workstation tools.

$ yum install krb5-workstation.x86_64

Test the keytab-file

$ kinit -k -t /etc/httpd/conf/webpage.HTTP.keytab HTTP/webpage.contoso.com

Test user login:

$ kinit <a domain username>@CONTOSO.COM

Check kerberos tickets:

$ klist

Delete the kerberos ticket:

$ kdestroy

14.4 View the apache logs

$ tail /var/log/httpd/error_log -n 15

A successfully kerberos-login should look like this in the log.
You may want to set apache LogLevel to debug (see 14.2).

[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1496): [client 172.27.10.101] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1496): [client 172.27.10.101] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1151): [client 172.27.10.101] Acquiring creds for HTTP@webpage.contoso.com
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1270): [client 172.27.10.101] Verifying client data using KRB5 GSS-API
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1286): [client 172.27.10.101] Verification returned code 0
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1304): [client 172.27.10.101] GSS-API token of length 161 bytes will be sent back
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1352): [client 172.27.10.101] set cached name <domainuser>@CONTOSO.COM for connection
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1496): [client 172.27.10.101] kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
[Wed Jan 14 10:45:52 2015] [debug] src/mod_auth_kerb.c(1527): [client 172.27.10.101] using cached name <domainuser>@CONTOSO.COM

A list of the error messages and description for each one can be viewed here: http://sammoffatt.com.au/…table_entry_not_found_while_getting_initial_credentials

Sources

Some of the sources refers to compiling the module for apache. I ONLY installed the mod_kerb_auth, and did not compile anything.

Update 2016-05-02: Found another howto guide to set up kerberos http://wiki.openiam.com/display/IAMSUITEV3/Kerberos+Authentication+When+Using+the+Reverse+Proxy