Attention

This document was written for an old version of Plone, Plone 3, and was last updated 117 days ago.

To learn how to upgrade to the current version of Plone, read the upgrade manual.

Minimal Single Sign On for Plone using Kerberos

by Duco Dokter last modified Jan 24, 2013 10:13 AM
This howto describes the minimal steps required for Single Sign On (SSO) for your Plone site, using the credentials you used for logging in to your machine.

Motivation

This document has been written during a SSO implementation for Plone on a Windows 2003 domain, so that the credentials used for logging in to the Windows domain are also used for logging in to Plone. This allows for seamless integration of a Plone intranet site for users. Most of the steps taken in this process were taken from the howto Single Sign On with Active Directory, but the process described here is somewhat simpler. Also, the alternative method of using NTLM is left out, since NTLM is deprecated for Windows domains, and the software needed for NTLM is abandoned.

Assumptions

The setup is based on a Windows 2003 domain, using Active Directory (ADS) for authentication/authorization. The clients used are also Windows clients (using Citrix), using both FireFox 3.x and Internet Explorer 7. The server used for Plone is a Suse Linux 11.2, but any  Linux distribution should have more or less the same packages and setup. Apache 2.x is used as a front-end for Plone. All FireFox, Chrome and IE browsers support SSO settings officially.

It is assumed you have set up Plone using buildout, and have it running on the same machine as the Apache server, on port 8080. Your Plone site within Zope has the id 'plone'.

Our example setup:

Windows domain
EVILEMPIRE.LAN
intranet site
intranet.evilempire.lan
Windows domain controller (primary)
dc01.evilempire.lan
Windows domain controller (backup)
dc02.evilempire.lan

How does it actually work?

The SSO process works as follows, given that a user has logged in to her/his machine and navigates to the intranet site on http://intranet.evilempire.lan/: Apache decides that this site/location is restricted access and uses the Apache Kerberos authentication module to negotiate with the client how access can be gained. The client (FireFox or IE) receives a challenge for authentication, and sends the credentials of the currently logged in user. The Apache Kerberos module checks the credentials with ADS (Kerberos server) and if ok, sets the username into an environment variable, before proxying the request to Plone. Plone recieves the request and can, using the WebServerAuth module, retrieve the credentials from the environment variable, and tell Plone you are logged in.

Implementation phases

The process can split into smaller parts, that enable testing of each step. The parts are:

  • enable Kerberos on the webserver machine;
  • enable Kerberos authentication for Apache;
  • enable webserver authentication for Plone;
  • enable SSO with the logged in Windows user.

Enable Kerberos on your server

To enable Kerberos on the server, you'll need the Kerberos libraries to be installed. These are in the krb5 package and may already be installed. For testing purposes some handy client side tools are available as well. Install this package: krb5-client. Configure /etc/krb5.conf as per your needs. In the example case, it would be something like

[libdefaults]
        default_realm = EVILEMPIRE.LAN
        clockskew = 300

[realms]
        EVILEMPIRE.LAN = {
                kdc = dc01.evilempire.lan
                kdc = dc02.evilempire.lan
                default_domain = EVILEMPIRE.LAN
        }

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

Note the clockskew statement... For any server to be able to authenticate against a Kerberos server, the system time of the client should really not be to far off the system time of the Kerberos server. It is convenient to make sure this is the case, by using the ntp daemon (package ntp), and using the Kerberos server as the master time server. Add these lines to the ntp.conf file:

server dc01.evilempire.lan prefer
server dc02.evilempire.lan

and comment out any other servers.

Make sure you have a user account in the ADS. Let's say the account name is 'plone'. You can now test your Kerberos setup using the 'kinit' tool. Calling it like this:

kinit plone

you should be asked to type your password, and on success Kerberos will grant you a ticket. You can check whether you actually got a ticket with the klist command. It should give you output like this:

Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: plone@EVILEMPIRE.LAN

Valid starting     Expires            Service principal
03/24/10 14:32:55  03/25/10 00:32:58  krbtgt/EVILEMPIRE.LAN@EVILEMPIRE.LAN
    renew until 03/25/10 14:32:55

if all is well, you now have enabled calling Kerberos authentication from your server.

Enabling Kerberos for Apache

To enable Apache authentication using a Kerberos server (or ADS for that matter), you'll need to install the mod_auth_kerb module for Apache. For Debian, this module is available as libapache2-mod-auth-kerb, for SuSe/RedHat you can fetch the package from rpmbone. The package is called apache2-mod_auth_kerb-<version>.<arch>.rpm.

After installation, enable it by either manually making sure it gets loaded by Apache on startup (this is configured differently on SuSe and Debian), or using the command a2enmod that is distro independent and takes care of the proper configuration for your distro.

a2enmod mod_auth_kerb

This module gives you some directives to enable Kerberos authentication for your webserver. An example configuration is given for a virtualhost intranet.evilempire.lan:

<VirtualHost *:80>
    ServerAdmin webmaster@evilempire.lan
    ServerName intranet.evilempire.lan
    DocumentRoot /var/www/intranet.evilempire.lan

    <Directory "/var/www/intranet.evilempire.lan">
      AllowOverride None
      Allow from all
    </Directory>
    <Location />
        AuthType Kerberos
        AuthName "Kerberos Login"
        KrbMethodNegotiate On
        KrbMethodK5Passwd On
        KrbVerifyKDC Off # On
        KrbAuthRealms EVILEMPIRE.LAN
        Krb5Keytab /etc/apache2/krb5.keytab
        KrbServiceName HTTP/intranet.evilempire.lan@EVILEMPIRE.LAN

        Require valid-user
    </Location>
</VirtualHost>

Last but not least, you'll need to generate a keytab file that holds the ticket that the Kerberos module will use to contact the Kerberos server, This can be created on the ADS machine with the following command:

ktpass -out c:\plone.keytab /princ 
  HTTP/intranet.evilempire.lan@EVILEPMIRE.LAN
  /pass <your secret password> 
  -mapOp set /ptype KRB5_NT_PRINCIPAL /mapUser plone

N.B.: the command is really one line, but hey, doesn't this read a bit easier? It is rather hard to find info on other ways to create the keytab file, but anyone that has more info is invited to add a comment, and I'll incorporate it into this howto.

You should now have a file called plone.keytab on your C drive. This file needs to be transported (safely) to your server, using scp, sftp or the likes. When you have the file on your server, name it to the location you have configured in the virtual host directive Krb5Keytab. Note: if you have more keytab files, you can merge them using the 'ktutil' command. This enables you to read multiple keytab files, and write as one. 'man ktutil' should give you the idea...

Now if you add this configuration to Apache, restart the web server, and navigate to this site, assuming you have provided a page called index.html, with the URL http://intranet.evilempire.lan/index.html, you should be challenged with a popup, saying 'Kerberos Login'.

Enable webserver authentication for Plone

Assuming you got this far, it is now time to enable the authentication that you have in place for Plone. This basically boils down to setting up the WebServerAuth module for Plone. In you buildout config file, add Products.WebServerAuth to the eggs section, rebuild and go to the ZMI, quickinstaller. Install WebServerAuth. Now navigate to the acl_users of your Plone. There should be a webserverauth plugin there. If not, pick it from the list of addable types. Depending on your setup, you may need to configure the webserverauth plugin, depending on the type of login names that are used in the Windows domain.

This plugin basically tells Plone that whatever user is given in the configured header (X_REMOTE_USER) is to be trusted by Plone. Please note that anyone can actually pass this header to any request, so this is a dangerous way of authentication if you don't secure the process!

So now the only thing left here, is to make sure that the user that logs in with the Kerberos authentication module is set in this header. For this you'll need to activate three more Apache modules (you know how to do that now...): rewrite, headers and proxy_http. (Please note that some distro's will not automatically also enable dependencies. For SuSe for instance, make sure you enable the proxy module as well, and before you enable proxy_http.)

Below is given an example configuration, using virtual host:

<VirtualHost *:80>
    ServerAdmin webmaster@evilempire.lan
    ServerName intranet.evilempire.lan

    <Directory "/var/www/intranet.evilempire.lan">
      AllowOverride None
      Allow from all
    </Directory>
    <Location />
        AuthType Kerberos
        AuthName "Kerberos Login"
        KrbMethodNegotiate On
        KrbMethodK5Passwd On
        KrbVerifyKDC Off # On
        KrbAuthRealms EVILEMPIRE.LAN
        Krb5Keytab /etc/apache2/krb5.keytab
        KrbServiceName HTTP/intranet.evilempire.lan@EVILEMPIRE.LAN

        Require valid-user
        RequestHeader set X_REMOTE_USER %{remoteUser}e
    </Location>

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    RewriteEngine On

    RewriteRule ^/(.*)$ http://localhost:8080/VirtualHostBase/http/intranet.evilempire.lan:80/plone/VirtualHostRoot/$1 [L,P,E=remoteUser:%{LA-U:REMOTE_USER}]

</VirtualHost>

 

The Proxy directive is somewhat odd, and so is the setting of the remoteUser variable, but there seem to be some problems with the remote user setting that are resolved this way...

Navigating to the intranet again, after restarting Apache of course, should now again give a popup, and should log you in to Plone using your Windows login name.

SSO

The last part is to automatically use your Windows login name for login to Plone, withou the popup. This is really only a matter of configuration of your browser. In the case of FireFox, open a tab, and type the url: about:config. Filter on 'network.nego'. Edit the 'network.negotiate-auth.trusted-uris' directive to include the 'evilempire.lan' domain.

In case of IE, goto Tools->Internet Options->Security. The setting you'll need depends a bit on the situation. If your intranet is recognized as such (see the icon on the browser footer), you need to change the settings for that, otherwise change the settings for internet sites. You may even add the site to trusted sites, but then you'll need https (you may want that anyway... read on!).

For the given class of your site, go to Custom Level->User authentication->Logon and select either 'Automatic logon only in Intranet zone' or 'Automatic logon with current user name and password'.

Restart IE (sure..!) and when navigating to the intranet site, you should automatically be logged in!

N.B. Make sure that the domain used for the Plone site is a primary domain in the DNS settings on your Windows domain, and that it is regarded as a 'trusted site' by your IE!

Further steps

The setup as described above completes the SSO part, but there is some more steps you may want to do:

  • securing the setup
  • adding ADS as back-end for Plone users

Security

The setup so far has two main security risks:

  • the fallback for when SSO fails is still to use the Basic challenge with a popup. This causes the password of the user to travel over the network unencrypted. This may or may not be a problem in your situation.
  • the X_REMOTE_USER can simply be added to any request to Plone. Since Plone assumes that this header contains the actual user, anyone could be logging in as 'admin' or anyone else. This may not be a problem to you, but it's hard to see that...

To make the setup more secure, it is recommened that you enable SSL for the intranet, and use it over HTTPS only. This howto will not describe how to do that, plenty others will...

To prevent abuse of the X_REMOTE_USER header, make sure that the intranet is only reachable through Apache (you can use a firewall for that).

ADS as user back-end

Since we're using ADS to authenticate to, we may as well use the same user database as back-end for Plone. For this you'll need Products.PloneLDAP. The process is fully described in Single Sign On with Active Directory. However, there's a few considerations. Make sure that you have the packages openldap2-client and openldap2-devel installed. The first is handy for testing, the latter is required for python-ldap, that is installed as a dependency for PloneLDAP.

If the LDAP client stuff is installed, check whether you can actually connect to the ADS:

ldapsearch -h dc01.evilempire.lan -s base -x -LLL -b "" "objectClass=*"

This should give you some info on the ADS root. At least you should get no error. You should determine the base for users in ADS in normal LDAP terms, which may take some time... Usually you'll have the domain as base, and then organisational units as sub containers. Your mileage may vary, but something along these lines: ou=Users,dc=evilempire,dc=lan.

Per default, anonymous access to ADS is not allowed any deeper than root level, so use your plone user to test access to the users:

ldapsearch -h dc01.evilempire.lan  -x -LLL -D "plone@evilempire.lan" -W -b "ou=Users,dc=evilempire,dc=lan"

This should give you a password prompt, and after that a list of user details. The bind name (after '-D') depends on the ADS user name configuration. Please check with your sysadmin.

When configuring the ADS plugin, make sure your base property is syntactically correct, otherwise you'll get a nasty DECODE error thrown at you.


Contribute

Something wrong or out of date? Anybody can edit or create a new article in the knowledge base. Simply create an account on this site, log in, and click the Edit button to contribute.