JavaHowTo

The Shibboleth SP is presently only implemented in C++ as a module for Apache, IIS, and so forth. However, it's straightforward to use it to provide authentication and authorization for Java servlets in servlet containers by tunneling or proxying requests through a supported web server.

Requests from the browser are intercepted first by Apache. After a Shibboleth SP session is established, the SP or Apache can enforce access control rules, or it can just pass attributes along to an application. The request is then forwarded to the servlet through the use of the AJP binary protocol, or alternatively via HTTP reverse proxying. Subsequent requests can leverage the Shibboleth session or a session maintained by the application or servlet container to persist the login.

Note that it's certainly possible to do all this with IIS, but it is not recommended and is beyond the scope of this example.

1. Setup Apache with Shibboleth

Install Apache first. All supported versions include mod_proxy_ajp in the main distribution.

Next, install Shibboleth itself. This is a platform-dependent decision, so go back to the main installation page and select the one that applies. After you complete the installation process, please return here and continue.

2. (Optional) Setup AJP13 support in your servlet container

While HTTP proxying is a possible approach, if AJP is supported that is a recommended choice because it is allows applications to operate somewhat more securely (though in practice, the real issue is the same: you MUST secure the connection between Apache and the servlet container). The main difference is that with HTTP proxying, it's easier to make a mistake and accidentally expose the back-end container to direct access by a browser, and once that's done, all security is lost due to the ease of smuggling headers into the application. It also makes establishing the REMOTE_USER variable more complex since it would depend on a Java filter establishing it from a header.

Assuming AJP, This step depends on your servlet container, but Tomcat and its derivatives have an AJP connector commented out by default.

  • Setting the tomcatAuthentication="false" attribute on the AJP <Connector> element allows REMOTE_USER to be automatically set based on what Apache has set. See Tomcat's AJP Connector documentation for more details.

  • Recent Tomcat versions also limit the acceptance of any attributes, and the allowedRequestAttributesPattern setting must be added to approve the attribute names to accept (or wildcarded).

Be careful that there is no direct HTTP listener opened by the servlet container.

If, for example, there's an HTTP connector listening on port 8080 and no interceding firewall, users would be able to directly access the servlet on port 8080, which bypasses Apache. This also means they would bypass Shibboleth authentication and authorization.

AJP packet size

Service Providers that leverage many attributes or receive many attribute values can expect to exceed the default maximum AJP packet size (8kb). In order to prevent this, raise the maximum AJP packet size to 65kb (maximum allowed by the AJP protocol) or whatever value in between makes sense.This value should be specified both in Apache and your servlet container configuration.

  • Tomcat: Add a packetSize="65536" to the AJP <Connector> element.

  • Apache with mod_jk: Add a worker.<name>.max_packet_size directive to the worker definition.

    worker.<name>.max_packet_size=65536



  • Apache with mod_proxy_ajp: Add a ProxyIOBufferSize directive to Apache's configuration.

    ProxyIOBufferSize 65536



3. Configure Apache to route requests to your servlet

Add a line to your Apache configuration, often in a <VirtualHost> definition, to proxy requests to your application through AJP:

ProxyPass /my-application ajp://localhost:8009/my-application

Note that you probably don't want to proxy the root of the server, but if you did want to "relocate" a servlet application to the Apache root that way, you'll need to exclude the SP's handler URLs from this proxying:

4. Add Shibboleth protection for your servlet

This is dependent on the way you want to integrate your application with the SP, but you could for example add a line to your Apache configuration on the proper virtual host to trigger Shibboleth session initiation and authentication for your application:

Since environment variables are not passed by mod_proxy_ajp unless they have AJP_ prefixes, you'll also need to add attributePrefix="AJP_" to the <ApplicationDefaults> (or in rare cases an appropriate <ApplicationOverride>) element in your configuration:

In a Java web application, environment variables can be accessed by calling the HttpServletRequest.getAttribute method. Note that Tomcat's implementation of the getAttributeNames method is broken, as described in the following thread in the Shibboleth users mailing list.

Struts 2 Issue

When deploying an application written using the Struts 2 framework, see the Java example section on the attribute access page for an issue with retrieving attribute values with certain problematic names.