Single Sign-On with Kerberos, Apache's httpd and Linux

WORK IN PROGRESS

Updates:

  • 2015-03-05 Testing shows that OK_TO_DELEGATE flag not required for httpd server

Contents


Goal

User's log-in to their workstation or desktop once with their Kerberos username and password. Then, when using their preferred web browser, their credentials are automatically collected from the local Kerberos ticket cache by their browser and passed to the web server to authenticate them and grant them access without them having to supply either their user name or password.


Configuration

Network environment

  • Network: 192.168.251.0/24 + 192.168.254.0/24
  • Domain: my.desk

Linux Apache httpd server

  • Host: exampleweb.my.desk
  • Address: 192.168.251.12
  • OS: CentOS Linux release 7.0.1406 (Core)

krb5.conf

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

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 allow_weak_crypto = true
 default_realm = AD.UNSW.EDU.AU
# default_realm = DOOKEY.DOOKEY
# default_realm = MY.DESK
# default_ccache_name = KEYRING:persistent:%{uid}

[realms]
 AD.UNSW.EDU.AU = {
  kdc = ad.unsw.edu.au
#  admin_server = ad.unsw.edu.au
 }
 DOOKEY.DOOKEY = {
  kdc = win2k8r2ent.my.desk
#  admin_server = win2k8r2ent.my.desk
 }
 MY.DESK = {
  kdc = kerberos.my.desk
#  admin_server = kerberos.my.desk
 }

[domain_realm]
 .my.desk = MY.DESK
 .ad.unsw.edu.au = AD.UNSW.EDU.AU
 ad.unsw.edu.au = AD.UNSW.EDU.AU

httpd.conf

ServerRoot "/etc/httpd"

Listen 80

Include conf.modules.d/*.conf

User apache
Group apache

ServerAdmin plinich@cse.unsw.edu.au

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DocumentRoot "/var/www/html"

<Directory "/var/www/html">
    Options None
    AllowOverride All
    Require all granted
</Directory>

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

<Directory "/var/www/cgi-bin">
    Options None
    AllowOverride All
    Require all granted
</Directory>

ScriptAlias /cgi-bin-sso/ /var/www/cgi-bin-sso/

<Directory "/var/www/cgi-bin-sso">
    Options None
    AllowOverride All
    Require all granted
</Directory>

ErrorLog "logs/error_log"

#LogLevel warn
LogLevel debug

LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %p %l %u %t \"%r\" %>s %b" custom
CustomLog "logs/access_log" custom

TypesConfig /etc/mime.types

AddDefaultCharset UTF-8

MIMEMagicFile conf/magic

EnableSendfile on

IncludeOptional conf.d/*.conf

Include sites/*.site

exampleweb.site

<VirtualHost 0.0.0.0:80>
	RewriteEngine On
	RewriteRule ^(.*) https://%{HTTP_HOST}$1 [L,R]
</VirtualHost>

exampleweb_ssl.site

SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5

<VirtualHost 0.0.0.0:443>
	SSLEngine on
	SSLCertificateFile /var/www/ssl/server.crt
	SSLCertificateKeyFile /var/www/ssl/server.key
</VirtualHost>

/var/www/cgi-bin-sso/.htaccess

#==========
# .htaccess
#==========

SSLRequireSSL

DirectoryIndex		disabled

AuthType		Kerberos
AuthName		"Enter your MY.DESK username and password"
KrbAuthRealms		MY.DESK
KrbVerifyKDC		off
#KrbMethodNegotiate	off

KrbMethodK5Passwd	off
KrbMethodNegotiate	on

Require			valid-user

/var/www/cgi-bin-sso/view_sso_cgi_environment

#!/bin/sh

echo "Content-Type: text/html"
echo ""
echo "<html>"
echo "<head>"
echo "<title>SSO CGI environment</title>"
echo "</head>"
echo "<body>"
echo "<h1>SSO CGI environment</h1>"
echo "<pre>"
env | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
echo "</pre>"
echo "</body>"
echo "</html>"

Kerberos KDC

  • Host: kerberos.my.desk
  • Address: 192.168.254.4
  • OS: CentOS release 6.6 (Final)

kdc.conf

[kdcdefaults]
 kdc_ports = 88
 kdc_tcp_ports = 88

[realms]
 MY.DESK = {
  #master_key_type = aes256-cts
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  dict_file = /usr/share/dict/words
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
 }
[root@kerberos ~]#

The principals

[root@kerberos ~]# kadmin.local
Authenticating as principal root/admin@MY.DESK with password.

kadmin.local:  listprincs
HTTP/exampleweb.my.desk@MY.DESK
K/M@MY.DESK
kadmin/admin@MY.DESK
kadmin/changepw@MY.DESK
kadmin/kerberos.my.desk@MY.DESK
krbtgt/MY.DESK@MY.DESK
master@MY.DESK

kadmin.local:  getprinc master
Principal: master@MY.DESK
Expiration date: [never]
Last password change: Fri Feb 27 13:25:45 AEDT 2015
Password expiration date: [none]
Maximum ticket life: 1 day 00:00:00
Maximum renewable life: 0 days 00:00:00
Last modified: Fri Feb 27 13:28:23 AEDT 2015 (root/admin@MY.DESK)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 6
Key: vno 1, aes256-cts-hmac-sha1-96, no salt
Key: vno 1, aes128-cts-hmac-sha1-96, no salt
Key: vno 1, des3-cbc-sha1, no salt
Key: vno 1, arcfour-hmac, no salt
Key: vno 1, des-hmac-sha1, no salt
Key: vno 1, des-cbc-md5, no salt
MKey: vno 1
Attributes: OK_AS_DELEGATE
Policy: [none]

kadmin.local:  getprinc HTTP/exampleweb.my.desk
Principal: HTTP/exampleweb.my.desk@MY.DESK
Expiration date: [never]
Last password change: Fri Feb 27 13:33:29 AEDT 2015
Password expiration date: [none]
Maximum ticket life: 1 day 00:00:00
Maximum renewable life: 0 days 00:00:00
Last modified: Fri Feb 27 13:33:29 AEDT 2015 (root/admin@MY.DESK)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 6
Key: vno 2, aes256-cts-hmac-sha1-96, no salt
Key: vno 2, aes128-cts-hmac-sha1-96, no salt
Key: vno 2, des3-cbc-sha1, no salt
Key: vno 2, arcfour-hmac, no salt
Key: vno 2, des-hmac-sha1, no salt
Key: vno 2, des-cbc-md5, no salt
MKey: vno 1
Attributes: OK_AS_DELEGATE
Policy: [none]

kadmin.local:  q

[root@kerberos ~]#

Note that the OK_AS_DELEGATE attribute is set for both principals.

Mac OS X Yosemite desktop

  • Host: macmini.my.desk
  • Address: 192.168.254.3
  • OS: Mac OS X Yosemite 10.10.2

krb5.conf

[libdefaults]
	default_realm = AD.UNSW.EDU.AU
#	allow_weak_crypto = true
[realms]
	AD.UNSW.EDU.AU = {
		kdc = ad.unsw.edu.au
#		admin_server = kerbnfssrvr.my.desk
	}
	MY.DESK = {
		kdc = kerberos.my.desk
	}
[domain_realm]
	.my.desk = MY.DESK
	.ad.unsw.edu.au = AD.UNSW.EDU.AU
	ad.unsw.edu.au = AD.UNSW.EDU.AU

Firefox

about:config → network.negotiate-auth.trusted-uris → .my.desk

After connecting...

$ klist
Credentials cache: API:61376022-8DC9-44D4-A65A-EBA2AE885CE9
        Principal: master@MY.DESK

  Issued                Expires               Principal
Mar  5 12:25:07 2015  Mar  5 22:25:04 2015  krbtgt/MY.DESK@MY.DESK
Mar  5 12:25:10 2015  Mar  5 22:25:04 2015  HTTP/exampleweb.my.desk@MY.DESK
$

Safari

Version: 8.0.3

Works immediately. No changes required.