Delegating Credentials to an Application Server

One common use-case of credential delegation is where a client chooses to allow a server to authenticate to and perform actions on a second server as the client.

Example use-case

An Administrative Assistant opens her IE Browser (client) and goes to her company's intranet (server). The intranet has a feature where she can schedule reports to be printed later that night. This allows her to go home early and avoid having to wait until the system is done processing the day's transactions.

The reporting server runs on a (second server) different host than the intranet server. The reporting server maintains certain preferences based on who is running the report. Because of this, later that night when the intranet server connects to the reporting server to run a report, the reporting server will think it's the admin assistant running the report.

Hence, the report will be printed after applying the admin assistant's preferences: the right printer, in the right font-size, stapled, etc.

CLIENT1 --(allow delegation)--> SERVER1 --(as the admin asst)--> SERVER2

Before Getting Started

Be sure that you have read and successfully performed ALL of the steps in the pre-flight documentation before proceeding any further. It is imperative that you perform all steps in the pre-flight since we will be using files that we created from that guide.

If you don't already have a working app server that authenticates requests via Kerberos/SPNEGO, take a look at the installing Tomcat or installing JBoss example. You will need to do this twice since this example requires one client machine and two (2) servers.

Allowing Delegation

By default, Internet Explorer (IE) and Active Directory (AD) have delegation enabled. However, there are a few steps that need to be performed before credential delegation can occur.

The pre-flight documentation describes a pre-authentication Windows Domain Account that the app server uses to authenticate client requests. This pre-authentication account must be specified in Active Directory as "Account is trusted for delegation".

The SPNEGO Http Servlet Filter's init params in the app server's web.xml file will also need to be modified to allow delegation.

Taking the example use-case from earlier, only the intranet server needs to be allowed for delegation. Meaning, only the intranet server's pre-auth account and the intranet server's web.xml file needs to be modified.

Creating hello_delegate.jsp

If you are installing on Tomcat, create the following hello_delegate.jsp file under the \Program Files\Apache Software Foundation\Tomcat 6.0\webapps\ROOT directory of the server that will be making the call to the second server.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page import="java.net.*" %>
<%@ page import="org.ietf.jgss.*" %>
<%@ page import="net.sourceforge.spnego.*" %>
<html>
<head>
    <title>Hello Delegate Example</title>
</head>
<body>
<%
    if (request instanceof DelegateServletRequest) {
        DelegateServletRequest dsr = (DelegateServletRequest) request;
        GSSCredential creds = dsr.getDelegatedCredential();

        if (null == creds) {
            out.print("No delegated creds.");
        } else {
            out.print(creds.getName().toString()); 

            SpnegoHttpURLConnection spnego = 
                new SpnegoHttpURLConnection(creds);

            spnego.connect(new URL("http://perseus.athena.local:8080/hello_spnego.jsp"));

            out.print("<br />HTTP Status Code: " + spnego.getResponseCode());
            out.print("<br />HTTP Status Message: " + spnego.getResponseMessage());
            spnego.disconnect();
        }
    
    } else {
        out.print("Request not a delegate.");
    }
%>
</body>
</html>

Notice from the jsp code above that it is making a call to the second server named PERSEUS. Remember to replace this value with the name of your second server

Also, notice that the delegation example code did NOT have to be implemented as a .jsp file. We could have implemented this as a Servlet Filter, a Servlet or a Custom Tag.

Testing hello_delegate.jsp

Before running the hello_delegate.jsp, confirm that your first server and second server are working as expected by running the hello_spnego.jsp file.

First Server:

Second Server:

Notice from above that the first server is named MEDUSA and the second server is named PERSEUS.

We will now run the hello_delegate.jsp code on MEDUSA from our workstation.

If all is working as expected, you should see the HTTP Status Code: 200 in the message.

Recall that the client is only making a call to the server named MEDUSA. Yet if you look at the Tomcat logs on the server named PERSEUS, you will find that a request was made to PERSEUS. Furthermore, this request appears to have been made by the same person making the request to MEDUSA.

...
Nov 1, 2009 6:38:29 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/30  config=null
Nov 1, 2009 6:38:29 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1439 ms
Nov 1, 2009 6:38:41 PM net.sourceforge.spnego.SpnegoHttpFilter doFilter
FINE: principal=dfelix@ATHENA.LOCAL
...

As you can see, IE has allowed the user's credentials to be delegated to MEDUSA and MEDUSA used those credentials to request a protected page on PERSEUS on behalf of the IE user.

Troubleshooting hello_delegate.jsp

If you did not get an output similar to the above, take a look at the Troubleshooting hello_delegate.jsp page.

Links:
pre-flight checklist
install guide - tomcat
install guide - jboss
install guide - glassfish
reference docs
api docs
download

Troubleshooting:
HelloKDC.java
hello_spnego.jsp
HelloKeytab.java
hello_delegate.jsp
SpnegoHelloClient.java
ExampleSpnegoAuthenticatorValve.java

Examples:
create keytab for client
create keytab for app server
credential delegation
protected SOAP Web Service
tomcat authenticator valve
jboss authenticator valve

Licensing:
GNU LGPL


© 2009 Darwin V. Felix. All rights reserved.