Apache with mod_auth_saml Receipe

Sampo Kellomäki (sampo@iki.fi)

While I am not a guru in Apache set-ups and others will do this much better, not to speak of the official documentation, I still find that to ensure initial success of the new installer, some help may be in order.

Consider this receipe only one of many possible set-ups and not necessarily even the best. The receipe worked for me in September 2008. If you come much later, things may have changed.

This Apache set-up illustrates mod_auth_saml. If you are interested in CGI, mod_php, or mod_perl use with Apache, or compilation of Apache httpd with above bits and pieces, please refer to Apache Setup Receipe

For more general information about ZXID.org compilation or APIs start reading in README.zxid.

1 Architectural Overview

1.1 Other documents


Fig-1: ZXID, via mod_auth_saml, adds to Apache httpd Single Sign-On (SSO), Attribute Broker, and XACML PEP Capabilities that can be used by existing static and dynamic content without alteration.

2 Introduction to mod_auth_saml

For avoidance of doubt, mod_auth_saml - based on zxid.org - is a separate project from mod_authn_casa, mod_scalp and mod_mellon, which provide somewhat similar functionality, but have different code bases. It may be possible to use all of these simultaneously, but this is not recommended unless you are an expert that can sort out the differences.

mod_auth_saml provides Apache2 native integration at authentication layer. The objective of mod_auth_saml is to cause Apache to trigger SAML 2.0 Single Sign-On instead of HTTP Basic or Digest authentication.

mod_auth_saml does not backend in any module in the mod_authn_* sense. All authentication information is obtained from the frontend IdP without consulting any backend. (However, the zxid.org session mechanism needs backend storage - once zxid.org is generalized to support other backends than the default file system, we may factor out the local session storage to a backend of its own.)

If you want to perform local authentication after the SSO, mod_auth_saml will provide for downstream mod_authz_* modules a (pseudonymous) user identifier that can be used to make the authorization decisions. It will also provide the attributes that were received in the SSO or that were retrieved by later web services calls (like ID-DAP or Personal Profile calls).

Eventually mod_auth_saml may call on a mod_authn_* backend to obtain additional local attributes (beyond the ones received in the SSO). Such call will use the pseudonym as key.

2.1 Compiling from Source

You may be able to get mod_auth_saml.so in binary form, in which case all you need to do is

  make dir   # Create /var/zxid hierarchy
  cp mod_auth_saml.so /usr/local/httpd/modules

For more in-depth compilation instructions, please refer to general ZXID documentation (README.zxid).

Before you try compilation and installation of mod_auth_saml, you should investigate what type of Apache install you have. Unfortunately different OS distributions do this differently, making it difficult to provide one set of instructions that would always work.

Out of box, zxid/Makefile assumes your Apache is installed where the Apache project source code distribution would put it, namely in APACHE_ROOT=/usr/local/httpd. You can change this by adding a new definition in localconf.mk.

On some distributions the Apache related files are scattered in many places that are not under any specific "root" directory. In these cases you may need to define separate variable for each use, e.g:

  localconf.mk:
  APACHE_INCLUDE=-I/usr/include/apache2
  APR_INCLUDE=-I/usr/include/apr-1.0
  APACHE_MODULES=/usr/lib/apache2/modules

To locate the correct directories, you can try

  find / -name ap_config.h
  find / -name apr.h
  find / -name mod_auth_basic.so

Once everything is correctly set up, you can compile and install by saying

  make apachezxid             # Compiles
  make apachezxid_install     # Copies
  make dir                    # Create directory structure

The installation step really just copies mod_auth_saml.so to modules/ subdirectory of the Apache installation.

2.2 Configuration and Testing

2.2.1 httpd.conf

First you have to make sure mod_auth_saml.so is located in the modules/ directory of your Apache httpd installation (e.g. /usr/local/httpd/modules/mod_auth_saml.so). Then you should pull the module into the configuration with directive:

  LoadModule auth_saml_module modules/mod_auth_saml.so

Next you should configure the Location protected by SSO:

  <Location /protected>
    Require valid-user
    AuthType "saml"
    ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"
  </Location>

The /protected is the directory you choose to protect. AuthType must be "saml". The ZXIDConf directive allows you to pass any and all ZXID configuration directives, using query string format. Please see main ZXID documentation (README.zxid) for full discussion of the configuration options.

While most options can be left at their default value, the URL always needs to be specified. It must match the domain name and the directory that you choose to protect. The final suffix /saml is used as communications end point during protocol exchanges. You can choose any word you want (i.e. need not be "saml"), but it must not conflict with any actual content in the directory and must be immediate child of the directory.

As of version 0.28 (Sept 2008) you still need to create actual file to correspond to the URL:

  touch /usr/local/httpd/htdocs/protected/saml

We expect to remove this requirement for dummy file in a future version.

2.2.2 Trying it out

Try accessing

  https://sp1.zxidsp.org:5443/protected/somefile

You should first land on IdP selection and then after authentication to the IdP, see the file, or error message if the file does not exist.

2.2.3 Setting up Circle of Trust

2.3 Real World Example

Assume you want to set up a complex web site with some areas protected strongly, others moderately, and some not at all.

  /          -- No protection
  /pers      -- Optional SAML SSO. If SSO has been performed, the
                content will be personalized. If no SSO has been
                performed -- or fails -- nonpersonalized content
                is served. Default IdP is used.
  /intra     -- Requires SAML SSO with default IdP
  /protected -- Requires any SAML SSO with choice of IdP
  /strong    -- Requires SAML SSO with strong credentials and choice of IdP
  /other     -- Independent SP colocated with same web server. Login
                to any of the first 4 directories does not count
                as login to /other. It is its own entity and needs
                separate SAML SSO.
  1. Here's how you would configure it in httpd.conf (SSL and other configuration items are as usual and are not reproduced here):

         LoadModule auth_saml_module modules/mod_auth_saml.so
         
         <Location /pers>
           Require valid-user
           AuthType "saml"
           ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"
           ZXIDConf "DEFAULTQS=l0https://s-idp.liberty-iop.org:8881/idp.xml=1%26fp=1"
         </Location>
         
         <Location /intra>
           Require valid-user
           AuthType "saml"
           ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"
           ZXIDConf "DEFAULTQS=l0https://s-idp.liberty-iop.org:8881/idp.xml=1%26fc=1"
           ZXIDConf "REQUIRED_AUTHNCTX=urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport$urn:oasis:names:tc:SAML:2.0:ac:classes:Strong"
         </Location>
         
         <Location /protected>
           Require valid-user
           AuthType "saml"
           ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"
           ZXIDConf "ANON_OK=/pers/"
           ZXIDConf "REDIR_TO_CONTENT=1"
         </Location>
         
         <Location /strong>
           Require valid-user
           AuthType "saml"
           ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"
           ZXIDConf "REQUIRED_AUTHNCTX=urn:oasis:names:tc:SAML:2.0:ac:classes:Strong"
           ZXIDConf "IDP_SEL_PAGE=/idpsel.cgi"
         </Location>
       
         <Location /other>
           Require valid-user
           AuthType "saml"
           ZXIDConf "PATH=/var/other/"
           ZXIDConf "URL=https://sp1.zxidsp.org:5443/other/saml"
           ZXIDConf "SES_COOKIE_NAME=OtherSes"
         </Location>

    Notes

    1. /pers, /intra, and /strong are "slaves" of /protected. This means they can have some settings of their own, but other settings, especially those that apply after SSO, are shared with /protected

    2. The slaves share Entity ID, session cookie, and session with the master.

    3. /other is genuinely different SP with its own Entity ID, cookie and session directory.

    4. The ANON_OK describes prefix under which SSO failure is not considered fatal. Currently there can only be one such prefix per master SP. This is known limitation.

    5. The REDIR_TO_CONTENT is set in master and shared with slaves. This causes the SSO to end with 302 redirection to the original content so that the URL in browser's address bar will appear clean. Without this option, the last step of the SSO protocol might be visible and since SSO terminates in master SP, the slaves would have their relative URLs wrong.

    6. The DEFAULTQS specification is used to simulate user submitting the IdP selection form. It is used for the SPs for which the IdP is always the same. The Query String can also have some other form fields that control things like the ispassive flag (fp=1) or the allowcreate flag (fc=1). To understand what fields are possible, you can "View Source" the regular IdP selection page. The value of the DEFAULTQS option needs to be URL encoded to prevent premature interpretation as multiple configuration options. In particular the ampersand must be encoded as %26.

    7. The IDP_SEL_PAGE allows you to build a fully custom IdP selection page. Here we use it for requesting strong authentication context. Other simpler ways to customize the IdP Selection Page exist, see e.g. IDP_SEL_TEMPL_FILE whose default value is "idpsel.html" (you can edit that file or "idpsel.css" for customization).

  2. Create directories in the web root according to above plan. You also need to create the /var/other hierarchy since you want to keep /other as separate entity from rest of the directories

         make dir ZXID_PATH=/var/other/

    N.B. The last slash is important.

    Make sure the web server process has file system permissions to write to /var/zxid and /var/other.

2.4 Testing

To enable debugging output, you should add

  ZXIDDebug "0x61"

to the above configuration.

  1. Make sure you are logged out from your IdP and SP (e.g. delete cookies in browser)

  2. https://sp1.zxidsp.org:5443/pers/env.cgi

  3. https://sp1.zxidsp.org:5443/intra/env.cgi

  4. https://sp1.zxidsp.org:5443/pers/env.cgi

  5. Logout by https://sp1.zxidsp.org:5443/protected/saml?o=m and clicking "Single Logout (R)"

2.5 mod_auth_saml FAQ

  1. How it actually works, does the module intercept every http request/response?

    It intercepts every HTTP request destined to URL prefixed by what appears in httpd.conf <Location> configuration, i.e. Apache itself prefilters by URL prefix.

    Then it checks if cookie session is present - if so, the request is passed through to rest of Apache processing. If not, it will start the SSO processing by presenting the IdP selection screen. Eventually this will be improved to attempt automatic detection of IdP, e.g. if there is only one IdP in the CoT.

    If the URL is the special one configured in

          ZXIDConf "URL=https://sp1.zxidsp.org:5443/protected/saml"

    it will pass control to the ZXID code.

    If SSO was triggered, the original URL is held in RelayState and once the SSO completes (which will happen at the special URL), a redirect is performed to the original URL found from RelayState. This could be used beneficially in unsolicited SSO as well.

  2. Does it have the reverse proxy functionality or is it located elsewhere?

    mod_auth_saml works at the same layer and much the same way as HTTP Basic authentication is implemented in Apache. It runs in the Apache process itself and does not invoke any external helper.

    It is not a reverse proxy. However, it is possible to configure a frontend Apache server, with mod_auth_saml, to act as a reverse proxy.http://www.apsis.ch/pound/) should not be difficult.))" alt=" ((Integrating zxid to a dedicated reverse proxy like Pound (http://www.apsis.ch/pound/) should not be difficult.))">

  3. Is it OS independant? I mean, works both for Apache-Linux and Apache-Windows and Apache-Solaris? I wonder not directly, but could be compiled, right?

    It should not be OS dependant. For Unixes I am pretty sure this is a fact. For Windows we need more testing (as of May 2008). It does not yet (May 2008) work in IIS.

  4. How the session creation at application is handled?

    The name of the cookie that ZXID sets is configurable (by default it is called ZXIDSES). This may be enough for some applications.

2.6 Important TODO items for mod_auth_saml

Memory management needs an audit. The problem centers around memory management of dependency libraries openssl and libcurl. Both libraries as well as ZXID itself have vectorable memory allocators, i.e. you can supply your own implementation of malloc(3) and free(3). This allows Apache pool allocation functions to be used instead of the traditional malloc(3) and free(3).

Unfortunately life is not that simple. Which pool should we use? The per request pool is suitable for most purposes, but how can we know for what purpose openssl and libcurl allocate memory? There is no easy way of knowing and the ephemeral nature of per request allocation may land us in trouble. Other option would be to allocate everything from global pool to make sure the memory will never be freed under us. Unfortunately memory from the global pool can not be freed. Thus we may be better sticking to malloc(3) and free(3).

To make matters worse, openssl is used by all of zxid, libcurl, and Apache mod_ssl. Which one gets to set the function pointers that point to the allocator? There is no easy answer - or at least we have not seen one yet.

The allocator problems may be just about manageable for Apache running in traditional pre-fork server mode, but become a real nightmare for threaded execution modes.

2.7 mod_authz_xacml

We plan to develop a mod_authz_* layer module that will perform the authorization using XACML. mod_authz_xacml will act as a PEP and pass all available session attributes to a PDP and then act on the decision of the PDP to deny or permit access to a web resource. This is still WIP.

3 Conclusion

If you have any trouble, please do not hesitate to contact the author.