Adding Authentication Mechanisms to the GlassFish Servlet Container

by Ron Monzillo

This tip will show you how to implement and configure new authentication mechanisms in the GlassFish v2 servlet container. GlassFish v2 includes implementations of a number of HTTP layer authentication mechanisms such as Basic, Form, and Digest authentication. You can use the techniques described in this tip to add alternative implementations of the included mechanisms or to add implementations of new mechanisms such as HTTP Negotiate/SPNEGO, OpenID, or CAS.

GlassFish v2 and JSR 196

GlassFish v2 implements the Servlet Container Profile of JRS-196, Java Authentication Service Provider Interface for Containers. JSR 196 defines a standard service-provider interface (SPI) for integrating authentication mechanism implementations in message processing runtimes. You can use the techniques covered in this tip to add authentication mechanisms to GlassFish because GlassFish supports the JSR 196 standard. JSR 196 extends the concepts of the Java Authentication and Authorization Service (JAAS) to enable pluggability of message authentication modules in message processing runtimes. The standard defines profiles that establish contracts for the use of the SPI in specific contexts. The Servlet Profile of JSR-196 defines the use of the SPI by a Servlet container such that (1) the resulting container can be configured with new authentication mechanisms, and (2) the container employs the configured mechanisms in its enforcement of the declarative servlet security model (declared in a web.xml file using security-constraint elements).

The JSR 196 specification defines a simple message processing model composed of four interaction points, 2 on the client side, and 2 on the server side, as shown in Figure 1.

Security Processsing Injection Points

Figure 1. Security Processing Injection Points

A message processing runtime uses the SPI at these interaction points to delegate the corresponding message security processing to authentication providers, also called authentication modules, integrated into the runtime by way of the SPI.

A compatible server-side message processing runtime, such as the GlassFish servlet container, supports the validateRequest and secureResponse interaction points of the message processing model. The servlet container uses the SPI at these interaction points to delegate the corresponding message security processing to a server authentication module (SAM), integrated by the SPI into the container.

A key step in adding an authentication mechanism to a compatible server-side message processing runtime such as the GlassFish servlet container, is acquiring a SAM that implements the desired authentication mechanism. One way to do that is to write the SAM yourself, so let's examine how to do that.

Writing a SAM

A SAM implements the javax.security.auth.message.module.ServerAuthModule interface as defined by JSR 196 and is invoked (indirectly) by the message processing runtime at the validateRequest and secureResponse interaction points. A SAM must implement the five methods of the ServerAuthModule interface, each of which is described briefly below. See section "3. Servlet Container Profile" in the JSR 196 specification for additional background and details.

  • getSupportedMessageTypes()

    An array of

    Class

    objects where each element defines a message type supported by the SAM. For a SAM to be compatible with the Servlet Container profile, the returned array must include the

    HttpServletRequest.class

    and

    HttpServletResponse.class

    objects.

  • initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler Map options)

    The container calls this method to provide the SAM with configuration values and with a

    CallbackHandler

    . The configuration values are returned in the policy arguments and in the options

    Map

    . The SAM uses

    CallbackHandler

    to access services, such as password validation, provided by the container.

  • AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)

    The container calls this method to process each received

    HttpServletRequest

    . The request and its associated

    HttpServletResponse

    are passed by the container to the SAM in the

    messageInfo

    argument. The SAM processes the request and may establish the response to be returned by the container. The SAM uses the provided

    Subject

    arguments to convey its authentication results. The SAM returns different status values to control the container's invocation processing. The status values and the circumstances under which they are returned are as follows:

    • AuthStatus.SUCCESS is returned when the application request message is successfully validated. The container responds to this status value by using the returned client Subject to invoke the target of the request. When this value is returned, the SAM (provided a custom AuthConfigProvider is not being used) must use its CallbackHandler to handle a CallerPrincipalCallback using the clientSubject as an argument to the callback.
    • AuthStatus.SEND_CONTINUE indicates that message validation is incomplete and that the SAM has established a preliminary response as the response message in messageInfo. The container responds to this status value by sending the response to the client.
    • AuthStatus.SEND_FAILURE indicates that message validation failed and that the SAM has established an appropriate failure response message in messageInfo. The container responds to this status value by sending the response to the client.
    • AuthStatus.SEND_SUCCESS is not typically returned. This status value indicates the end of a multi-message security dialog originating after the service interaction and during the processing of the application response. The container responds to this status value by sending the response to the client.

    ValidateRequest may also throw an AuthException to indicate that the message processing by the SAM failed without establishing a failure response message in messageInfo.

  • secureResponse(MessageInfo messageInfo, Subject serviceSubject)

    The container calls this method before sending a response, resulting from an application invocation, to the client. The response is passed to the SAM in the

    messageInfo

    argument. In most cases, this method should just return the

    SEND_SUCCESS

    status.

  • cleanSubject(MessageInfo messageInfo, Subject subject)

    This method removes the mechanism specific principals and/or credentials from the subject. This method is not currently called by the container. A legitimate implementation could remove all the principals from the argument subject.

Sample SAM

The class MySam.java is a sample SAM implementation. Notice that the sample implements the five methods of the ServerAuthModule interface. For example, here is the implementation of the initialize() method:

   public void initialize(MessagePolicy reqPolicy,
           MessagePolicy resPolicy,
           CallbackHandler cBH, Map opts)
           throws AuthException {
       requestPolicy = reqPolicy;
       responsePolicy = resPolicy;
       handler = cBH;
       options = opts;
   }

Also notice that the validateRequest method is stubbed. For authorization-protected resources, validateRequest returns a "FORBIDDEN" status code along with the message "authentication required and not yet implemented." However, validateRequest allows access for unprotected resources by returning AuthStatus.SUCCESS. The SAM uses the return value of requestPolicy.isMandatory() to determine when the request is to an authorization-protected resource. The servlet container profile mandates that the message processing runtime establish the requestPolicy such it can be used by the SAM to determine when authentication is required.

       public AuthStatus validateRequest(
               MessageInfo msgInfo, Subject client,
               Subject server) throws AuthException {
           try {
               if (requestPolicy.isMandatory()) {
                   HttpServletResponse response =
                           (HttpServletResponse)
                           msgInfo.getRequestMessage();
                   response.setStatus
                     (HttpServletResponse.SC_FORBIDDEN);
                   response.sendError(
                     HttpServletResponse.SC_FORBIDDEN,
                     "authentication required and
                     not yet implemented");
                   return AuthStatus.SEND_FAILURE;

               } else {
                   setAuthenticationResult(null,
                           client, msgInfo);
                   return AuthStatus.SUCCESS;
               }
           } catch (Exception e) {
               AuthException ae = new AuthException();
               ae.initCause(e);
               throw ae;
           }
       }

Before you can use the sample SAM, you need to compile, install, and configure it. Then you can bind it to an application.

Compiling and Installing the SAM

To compile the SAM, you need to include the SPI in your classpath. When GlassFish is installed, the JAR file containing the SPI, jmac-api.jar, is installed in the lib subdirectory under the root of your GlassFish installation directory.

After you compile the SAM, install it by copying a JAR file containing the compiled SAM to the lib subdirectory under the root of the GlassFish installation directory.

Configuring the SAM

You can configure a SAM for GlassFish v2 using the GlassFish v2 Admin Console, officially known as the Sun Java System Application Server Admin Console. Here are the steps:

  1. Make sure the GlassFish V2 Application Server is running. If it is not already running, you can start it using the following command:
       <GF_HOME>bin/asadmin start-domain domain1
    

    where <GF_HOME> is the directory where you installed GlassFish v2.

  2. Open the GlassFish v2 Admin Console by pointing your browser to the URL: http://localhost:4848/.
  3. Login to the Admin Console by entering your ID and password.
  4. Expand the Configuration node at the bottom of the left-hand pane.
  5. Navigate to the Security node, expand it, and click MessageSecurity.
  6. Under Message Security Configurations, either open the HttpServlet layer if it already exists, or create it if it doesn't exist by clicking the New button. Clicking the button opens the New Message Security Configuration window.
  7. If you need to create the layer, you will need to configure the provider. To do that:

    If the HttpServlet layer already exists, do the following:

Note that the provider configuration utility also provides a dialog box that you can use to configure additional properties. If you configure additional properties in this way, the properties are passed in the options parameter when the SAM’s initialize method is called. The sample SAM in this tip does not require any initialization properties. However, another SAM, for example, could support a property naming the group principals to add as a side effect of a successful authentication.

At this point the SAM is installed and available for use by GlassFish v2.

Binding the SAM to Your Application

After you install and configure the SAM, you can bind it for use by the container on behalf of one or more of your applications. You have a few options in how you bind the SAM, depending on whether or not you are willing to repackage and redeploy your application.

Option1: If you are willing to repackage and redeploy, you can bind the SAM within the sun-web.xml file of your web application. You do this by configuring the httpservlet-security-provider attribute of the sun-web-app element to contain the provider id assigned when the SAM was installed, that is, MySam.

If you use the NetBeans IDE, open the configuration file (in the non-XML view) and select the General tab. Assign the provider id to the field titled Http Servlet Security Provider. You then need to rebuild and redeploy the application.

1 2 Page 1
Page 1 of 2