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).
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
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.
See the section below for a discussion on whether to use DSA or RSA.
# 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.
# openssl genrsa -out privkey.pem 2048 # openssl rsa -in privkey.pem -out pubkey.pem -pubout
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>
TKTAuthTimeoutURL, but in case the request was a POST
TKTAuthTimeoutURLis used (and if that is not set either,
TKTAuthToken) will be redirected to
graceperiodkey in the ticket) before the actual expiry will be redirected to. Only GET requests are redirected; POST requests are accepted normally. The script at this URL should check the ticket and issue a new one
Cookiethen the format of the value expects to be a valid cookie (subject to the
TKTAuthCookieNamedirective). Any other header assumes the value is a simple URL-encoded value of the ticket. The first header that has content is tried and any other tickets in other header(s) are ignored. example, use Cookie first, fallback to X-My-Auth:
TKTAuthHeader Cookie X-My-Auth
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:
The ticket string is saved URL-encoded in a domain cookie, usually named
auth_pubtkt, but this can be changed (using the
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.
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.
# 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).
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
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).