JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle GlassFish Server 3.1 Application Development Guide
search filter icon
search icon

Document Information


Part I Development Tasks and Tools

1.  Setting Up a Development Environment

2.  Class Loaders

3.  Debugging Applications

Part II Developing Applications and Application Components

4.  Securing Applications

Security Goals

GlassFish Server Specific Security Features

Container Security

Declarative Security

Application Level Security

Component Level Security

Programmatic Security

Roles, Principals, and Principal to Role Mapping

Realm Configuration

Supported Realms

How to Configure a Realm

How to Set a Realm for an Application or Module

Creating a Custom Realm

JACC Support

Pluggable Audit Module Support

Configuring an Audit Module

The AuditModule Class

The server.policy File

Default Permissions

System Properties

Changing Permissions for an Application

Enabling and Disabling the Security Manager

Configuring Message Security for Web Services

Message Security Providers

Message Security Responsibilities

Application Developer Responsibilities

Application Deployer Responsibilities

System Administrator Responsibilities

Application-Specific Message Protection

Using a Signature to Enable Message Protection for All Methods

Configuring Message Protection for a Specific Method Based on Digital Signatures

Understanding and Running the Sample Application

To Set Up the Sample Application

To Run the Sample Application

Programmatic Login

Programmatic Login Precautions

Granting Programmatic Login Permission

The ProgrammaticLogin Class

User Authentication for Single Sign-on

Adding Authentication Mechanisms to the Servlet Container

The GlassFish Server and JSR 196

Writing a Server Authentication Module

Sample Server Authentication Module

Compiling and Installing a Server Authentication Module

Configuring a Server Authentication Module

Binding a Server Authentication Module to Your Application

5.  Developing Web Services

6.  Using the Java Persistence API

7.  Developing Web Applications

8.  Using Enterprise JavaBeans Technology

9.  Using Container-Managed Persistence

10.  Developing Java Clients

11.  Developing Connectors

12.  Developing Lifecycle Listeners

13.  Developing OSGi-enabled Java EE Applications

Part III Using Services and APIs

14.  Using the JDBC API for Database Access

15.  Using the Transaction Service

16.  Using the Java Naming and Directory Interface

17.  Using the Java Message Service

18.  Using the JavaMail API


Adding Authentication Mechanisms to the Servlet Container

You can use JSR 196 in the web tier to facilitate the injection of pluggable authentication modules within the servlet constraint processing engine. The GlassFish Server includes implementations of a number of HTTP layer authentication mechanisms such as basic, form, and digest authentication. You can add alternative implementations of the included mechanisms or implementations of new mechanisms such as HTTP Negotiate/SPNEGO, OpenID, or CAS.

The following topics are addressed here:

The GlassFish Server and JSR 196

The GlassFish Server implements the Servlet Container Profile of JSR 196, Java Authentication Service Provider Interface for Containers. JSR 196 defines a standard service provider interface (SPI) that extends the concepts of the Java Authentication and Authorization Service (JAAS) to enable pluggability of message authentication modules in message processing runtimes. The JSR 196 standard defines profiles that establish contracts for the use of the SPI in specific contexts. The Servlet Container Profile of JSR 196 defines the use of the SPI by a Servlet container such that:

The JSR 196 specification defines a simple message processing model composed of four interaction points:

  1. secureRequest on the client

  2. validateRequest on the server

  3. secureResponse on the server

  4. validateResponse on the client

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 Server 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.

Writing a Server Authentication Module

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

A SAM implements the interface as defined by JSR 196. A SAM 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:

See the Servlet Container Profile section in the JSR 196 specification for additional background and details.

Sample Server Authentication Module

The class is a sample SAM implementation. Notice that the sample implements the five methods of the ServerAuthModule interface. This SAM implements an approximation of HTTP basic authentication.

package tip.sam;

   import java.util.Map;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import org.apache.catalina.util.Base64;

   public class MySam implements ServerAuthModule {

      protected static final Class[]
        supportedMessageTypes = new Class[]{

      private MessagePolicy requestPolicy;
      private MessagePolicy responsePolicy;
      private CallbackHandler handler;
      private Map options;
      private String realmName = null;
      private String defaultGroup[] = null;
      privte static final String REALM_PROPERTY_NAME =
      private static final String GROUP_PROPERTY_NAME =
      private static final String BASIC = "Basic";
      static final String AUTHORIZATION_HEADER =
      static final String AUTHENTICATION_HEADER =

      public void initialize(MessagePolicy reqPolicy,
              MessagePolicy resPolicy,
              CallbackHandler cBH, Map opts)
              throws AuthException {
          requestPolicy = reqPolicy;
          responsePolicy = resPolicy;
          handler = cBH;
          options = opts;
          if (options != null) {
              realmName = (String)
              if (options.containsKey(GROUP_PROPERTY_NAME)) {
                  defaultGroup = new String[]{(String)

      public Class[] getSupportedMessageTypes() {
          return supportedMessageTypes;

      public AuthStatus validateRequest(
              MessageInfo msgInfo, Subject client,
              Subject server) throws AuthException {
          try {

              String username =
                  processAuthorizationToken(msgInfo, client);
              if (username ==
                  null && requestPolicy.isMandatory()) {
                  return sendAuthenticateChallenge(msgInfo);

                 username, client, msgInfo);
             return AuthStatus.SUCCESS;

          } catch (Exception e) {
              AuthException ae = new AuthException();
              throw ae;

      private String processAuthorizationToken(
              MessageInfo msgInfo, Subject s)
              throws AuthException {

          HttpServletRequest request =

          String token =

          if (token != null && token.startsWith(BASIC + " ")) {

              token = token.substring(6).trim();

              // Decode and parse the authorization token
              String decoded =
                  new String(Base64.decode(token.getBytes()));

              int colon = decoded.indexOf(':');
              if (colon <= 0 || colon == decoded.length() - 1) {
                  return (null);

              String username = decoded.substring(0, colon);

             // use the callback to ask the container to
             // validate the password
            PasswordValidationCallback pVC =
                    new PasswordValidationCallback(s, username,
                    decoded.substring(colon + 1).toCharArray());
            try {
                handler.handle(new Callback[]{pVC});
            } catch (Exception e) {
                AuthException ae = new AuthException();
                throw ae;

            if (pVC.getResult()) {
                return username;
      return null;

   private AuthStatus sendAuthenticateChallenge(
           MessageInfo msgInfo) {

       String realm = realmName;
         // if the realm property is set use it,
         // otherwise use the name of the server
         // as the realm name.
         if (realm == null) {

          HttpServletRequest request =

          realm = request.getServerName();

       HttpServletResponse response =

       String header = BASIC + " realm=\"" + realm + "\"";
       response.setHeader(AUTHENTICATION_HEADER, header);
       return AuthStatus.SEND_CONTINUE;

   public AuthStatus secureResponse(
           MessageInfo msgInfo, Subject service)
           throws AuthException {
       return AuthStatus.SEND_SUCCESS;

   public void cleanSubject(MessageInfo msgInfo,
           Subject subject)
           throws AuthException {
      if (subject != null) {

   private static final String AUTH_TYPE_INFO_KEY =

   // distinguish the caller principal
   // and assign default groups
   private void setAuthenticationResult(String name,
           Subject s, MessageInfo m)
           throws IOException,
           UnsupportedCallbackException {
       handler.handle(new Callback[]{
           new CallerPrincipalCallback(s, name)
       if (name != null) {
         // add the default group if the property is set
           if (defaultGroup != null) {
               handler.handle(new Callback[]{
                   new GroupPrincipalCallback(s, defaultGroup)
           m.getMap().put(AUTH_TYPE_INFO_KEY, ""MySAM");

Note that the initialize method looks for the and properties. The property configures the default group assigned as a result of any successful authentication. The property defines the realm value sent back to the browser in the WWW-Authenticate challenge.

Compiling and Installing a Server Authentication Module

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

To compile the SAM, include the SPI in your classpath. When the GlassFish Server is installed, the JAR file containing the SPI, jmac-api.jar, is installed in the as-install/lib directory. After you compile the SAM, install it by copying a JAR file containing the compiled SAM to the as-install/lib directory.

Configuring a Server Authentication Module

You can configure a SAM in one of these ways:

Binding a Server Authentication Module 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 two options in how you bind the SAM, depending on whether you are willing to repackage and redeploy your application: