mod_auth_pubtkt: Documentation

Deployment considerations

Since the "valid until" field in a ticket is necessarily in absolute time (UNIX timestamp), the clocks of the ticket-generating login server and the ticket-verifying web servers need to be more or less in sync. The longer the ticket lifetime, the less important this becomes. It's generally good practice to keep your servers' time synchronized (using NTP, for example).

Downloading and installing the module (Unix)

Download the source code for the latest version of mod_auth_pubtkt here.

Decompress the downloaded archive and run the included "configure" script, specifying the path to apxs if necessary (use where apxs to find it). The Apache version should be detected automatically (but note that the configure/make scripts haven't been tested under anything but FreeBSD and Mac OS X):

# tar xzfv mod_auth_pubtkt-0.x.tar.gz
# cd mod_auth_pubtkt-0.x
# ./configure
# make
# make install

Downloading and installing the module (Windows)

The source tarball, which you can download in the Unix section above, also contains pre-compiled modules for Apache 2.0 and 2.2 (in the "bin" subdirectory):

Decompress the downloaded archive and copy the relevant module for the version of Apache you are using into the "modules" directory inside your Apache program directory, then follow the instructions below (which apply both to Unix and Windows machines). Make sure that you use an Apache version that is bundled with OpenSSL (even if you don't use HTTPS), as mod_auth_pubtkt needs it.

Note: Windows binaries for OpenSSL (you'll need the command-line openssl.exe to generate a key pair) can be found at http://www.slproweb.com/products/Win32OpenSSL.html.

Generating a key pair

See the section below for a discussion on whether to use DSA or RSA.

DSA:

# openssl dsaparam -out dsaparam.pem 2048
# openssl gendsa -out privkey.pem dsaparam.pem
# openssl dsa -in privkey.pem -out pubkey.pem -pubout

The dsaparam.pem file is not needed anymore after key generation and can safely be deleted.

RSA:

# openssl genrsa -out privkey.pem 2048
# openssl rsa -in privkey.pem -out pubkey.pem -pubout

Module configuration

First of all, make sure that the module is loaded:

LoadModule auth_pubtkt_module libexec/apache/mod_auth_pubtkt.so
AddModule mod_auth_pubtkt.c		# Apache 1.3 only

Here's a simple VirtualHost configuration with mod_auth_pubtkt as a starting point; the configuration directives are explained below.

Note that the AuthType mod_auth_pubtkt statement is required!

<VirtualHost *:80>
    ServerName myserver.mydomain.com
    DocumentRoot /path/to/my/htdocs
    
    TKTAuthPublicKey /etc/apache2/tkt_pubkey.pem
    
    <Directory /path/to/my/htdocs>
        Order Allow,Deny
        Allow from all
        
        AuthType mod_auth_pubtkt
        TKTAuthLoginURL https://sso.mydomain.com/login
        TKTAuthTimeoutURL https://sso.mydomain.com/login?timeout=1
        TKTAuthUnauthURL https://sso.mydomain.com/login?unauth=1
        TKTAuthToken "myserver"
        require valid-user
    </Directory>
</VirtualHost>

Directives for use in server config, virtual hosts and directory/location/.htaccess scope

Directives for use in directory/location/.htaccess scope

Ticket format

Authentication tickets to be processed by mod_auth_pubtkt are composed of key/value pairs, with keys and values separated by '=' and individual key/value pairs separated by semicolons (';'). The following keys are defined; mod_auth_pubtkt silently ignores unknown keys:

Here's an example of how a real (DSA) ticket looks:

uid=mkasper;cip=192.168.200.163;validuntil=1201383542;tokens=foo,bar;udata=mydata;
sig=MC0CFDkCxODPml+cEvAuO+o5w7jcvv/UAhUAg/Z2vSIjpRhIDhvu7UXQLuQwSCF=

The ticket string is saved URL-encoded in a domain cookie, usually named auth_pubtkt, but this can be changed (using the TKTAuthCookieName directive).

Generating tickets

An example implementation of a login/ticket generating script in PHP is provided with the distribution (in the php-login subdirectory). It uses a simple flat-file user database by default, but can easily be extended to support LDAP (e.g. using adLDAP), RADIUS and other authentication methods.

The ticket-generating (and verifying) functions are in pubtkt.inc. They use the OpenSSL command-line binary directly, for two reasons:

For Perl users, a module and example CGI script are provided in the perl-login subdirectory of the distribution.

If you use Ruby, there's a gem created by Matt Haynes that helps with generating tickets.

For Python users, Andrey Plotnikov has created a module for generating tickets.

Whether to choose RSA or DSA

For digital signatures, two public-key schemes are commonly used: RSA and DSA. This module supports both, but you need to choose one over the other. Put simply, and assuming that both offer the same security at similar key sizes, it's mostly a decision between speed and signature (ticket/cookie) length.

From a performance point of view, RSA is the clear winner, as each ticket only needs to be signed once, but usually verified many times on different servers. However, note that mod_auth_pubtkt caches tickets, so the verification only needs to be done once per server process and ticket (and not once per request).

If ticket size matters to you more than speed, then DSA is the better choice; otherwise, you're probably better off using RSA. In the end, it's mostly down to "religious" issues or what you're already using in your company.

Generating a ticket signature on the command line

# echo -n "uid=foobar;validuntil=123456789;tokens=;udata=" \
  | openssl dgst -dss1 -sign privkey.pem \
  | openssl enc -base64 -A

If TKTAuthDigest isn't being used, specify -dss1 for DSA, and -sha1 for RSA. Otherwise specify the TKTAuthDigest directive's algorithm (i.e. -sha256 for SHA256).

Verifying a ticket signature on the command line

Strip the signature off the ticket and Base64-decode it into a temporary file:

# echo "MC0CFQC6c....=" | openssl enc -d -base64 -A > sig.bin

Pipe the ticket value through openssl to verify the signature using the public key in pubkey.pem:

# echo "uid=foobar;validuntil=123456789;tokens=;udata=" \
  | openssl dgst -dss1 -verify pubkey.pem -signature sig.bin

Security considerations for domain cookies

Note that if rogue servers under your domain are a concern, the domain cookies used by mod_auth_pubtkt may pose a problem, since a rogue server can steal a legitimate user's ticket. This can be mitigated by marking the ticket cookie as "secure", so that it is only transported via HTTPS, which means that only servers with a valid SSL certificate for your domain can see the user's ticket (unless the user overrides security warnings in the browser). Also, including the client IP address in the ticket (as is recommended whenever possible) makes it harder to use a stolen ticket.

Another way to solve this would be to change the login server to check the "back" URL and, instead of issuing cookies directly, include the ticket in the redirect back to the web server with the desired resource, which can then install the ticket as a cookie under its own server name. This would require adding support for parsing tickets in GET parameters to mod_auth_pubtkt (could be backported from mod_auth_tkt). Also, the login server would need to keep a copy of the ticket stored in a cookie under its own server name so that the user only has to log in once, of course. Finally, since there would now be a cookie for each server, it would be much more difficult to properly log out (without closing the browser).