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.
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.
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:
ProxyPass /Shibboleth.sso/* !
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:
ShibRequestSetting requireSession 1
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:
<ApplicationDefaults id="default" policyId="default"
REMOTE_USER="eppn persistent-id targeted-id"
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.