Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

18.2. Role-Based Security in Applications

18.2.2. About Authentication

Authentication refers to identifying a subject and verifying the authenticity of the identification. The most common authentication mechanism is a username and password combination. Other common authentication mechanisms use shared keys, smart cards, or fingerprints. The outcome of a successful authentication is referred to as a principal, in terms of Java Enterprise Edition declarative security.
JBoss EAP 6 uses a pluggable system of authentication modules to provide flexibility and integration with the authentication systems you already use in your organization. Each security domain may contain one or more configured authentication modules. Each module includes additional configuration parameters to customize its behavior. The easiest way to configure the authentication subsystem is within the web-based management console.
Authentication is not the same as authorization, although they are often linked. Many of the included authentication modules can also handle authorization.

18.2.3. About Authorization

Authorization is a mechanism for granting or denying access to a resource based on identity. It is implemented as a set of declarative security roles which can be added to principals.
JBoss EAP 6 uses a modular system to configure authorization. Each security domain may contain one or more authorization policies. Each policy has a basic module which defines its behavior. It is configured through specific flags and attributes. The easiest way to configure the authorization subsystem is by using the web-based management console.
Authorization is different from authentication, and usually happens after authentication. Many of the authentication modules also handle authorization.

18.2.4. About Security Auditing

Security auditing refers to triggering events, such as writing to a log, in response to an event that happens within the security subsystem. Auditing mechanisms are configured as part of a security domain, along with authentication, authorization, and security mapping details.
Auditing uses provider modules. You can use one of the included ones, or implement your own.

18.2.5. About Security Mapping

Security mapping allows you to combine authentication and authorization information after the authentication or authorization happens, but before the information is passed to your application.
You can map principals (authentication), roles (authorization), or credentials (attributes which are not principals or roles).
Role Mapping is used to add, replace, or remove roles to the subject after authentication.
Principal mapping is used to modify a principal after authentication.
Attribute mapping is used to convert attributes from an external system to be used by your application, and vice versa.

18.2.6. Java Authentication and Authorization Service (JAAS)

Java Authentication and Authorization Service (JAAS) is a security API which consists of a set of Java packages designed for user authentication and authorization. The API is a Java implementation of the standard Pluggable Authentication Modules (PAM) framework. It extends the Java Enterprise Edition access control architecture to support user-based authorization.
In JBoss EAP 6, JAAS only provides declarative role-based security. For more information about declarative security, refer to Section 18.1.4, “About Declarative Security”.
JAAS is independent of any underlying authentication technologies, such as Kerberos or LDAP. You can change your underlying security structure without changing your application. You only need to change the JAAS configuration.

18.2.7. About Java Authentication and Authorization Service (JAAS)

The security architecture of JBoss EAP 6 is comprised of the security configuration subsystem, and application-specific security configurations which are included in several configuration files within the application.
Domain, Server Group, and Server Specific Configuration

Server groups (in a managed domain) and servers (in a standalone server) include the configuration for security domains. A security domain includes information about a combination of authentication, authorization, mapping, and auditing modules, with configuration details. An application specifies which security domain it requires, by name, in its jboss-web.xml.

Application-specific Configuration

Application-specific configuration takes place in one or more of the following four files.

Table 18.1. Application-Specific Configuration Files

File Description
ejb-jar.xml
The deployment descriptor for an Enterprise JavaBean (EJB) application, located in the META-INF directory of the archive. Use the ejb-jar.xml to specify roles and map them to principals, at the application level. You can also limit specific methods and classes to certain roles. It is also used for other EJB-specific configuration not related to security.
web.xml
The deployment descriptor for a Java Enterprise Edition (EE) web application. Use the web.xml to declare the resource and transport constraints for the application, such as limiting the type of HTTP requests that are allowed. You can also configure simple web-based authentication in this file. It is also used for other application-specific configuration not related to security. The security domain the application uses for authentication and authorization is defined in jboss-web.xml.
jboss-ejb3.xml
Contains JBoss-specific extensions to the ejb-jar.xml descriptor.
jboss-web.xml
Contains JBoss-specific extensions to the web.xml descriptor.

Note

The ejb-jar.xml and web.xml are defined in the Java Enterprise Edition (Java EE) specification. The jboss-ejb3.xml provides JBoss-specific extensions for the ejb-jar.xml, and the jboss-web.xml provides JBoss-specific extensions for the web.xml.

18.2.8. Use a Security Domain in Your Application

Overview

To use a security domain in your application, first you need to define the security domain in the server's configuration and then enable it for an application in the application's deployment descriptor. Then you must add the required annotations to the EJB that uses it. This topic covers the steps required to use a security domain in your application.

Warning

If an application is part of a security domain that uses an authentication cache, user authentications for that application will also be available to other applications in that security domain.

Procedure 18.1. Configure Your Application to Use a Security Domain

  1. Define the Security Domain

    You need to define the security domain in the server's configuration file, and then enable it for an application in the application's descriptor file.
    1. Configure the security domain in the server's configuration file

      The security domain is configured in the security subsystem of the server's configuration file. If the JBoss EAP 6 instance is running in a managed domain, this is the domain/configuration/domain.xml file. If the JBoss EAP 6 instance is running as a standalone server, this is the standalone/configuration/standalone.xml file.
      The other, jboss-web-policy, and jboss-ejb-policy security domains are provided by default in JBoss EAP 6. The following XML example was copied from the security subsystem in the server's configuration file.
      The cache-type attribute of a security domain specifies a cache for faster authentication checks. Allowed values are default to use a simple map as the cache, or infinispan to use an Infinispan cache.
      <subsystem xmlns="urn:jboss:domain:security:1.2">
          <security-domains>
              <security-domain name="other" cache-type="default">
                  <authentication>
                      <login-module code="Remoting" flag="optional">
                          <module-option name="password-stacking" value="useFirstPass"/>
                      </login-module>
                      <login-module code="RealmDirect" flag="required">
                          <module-option name="password-stacking" value="useFirstPass"/>
                      </login-module>
                  </authentication>
              </security-domain>
              <security-domain name="jboss-web-policy" cache-type="default">
                  <authorization>
                      <policy-module code="Delegating" flag="required"/>
                  </authorization>
              </security-domain>
              <security-domain name="jboss-ejb-policy" cache-type="default">
                  <authorization>
                      <policy-module code="Delegating" flag="required"/>
                  </authorization>
              </security-domain>
          </security-domains>
      </subsystem>
      You can configure additional security domains as needed using the Management Console or CLI.
    2. Enable the security domain in the application's descriptor file

      The security domain is specified in the <security-domain> child element of the <jboss-web> element in the application's WEB-INF/jboss-web.xml file. The following example configures a security domain named my-domain.
      <jboss-web>
          <security-domain>my-domain</security-domain>
      </jboss-web>
      This is only one of many settings which you can specify in the WEB-INF/jboss-web.xml descriptor.
  2. Add the Required Annotation to the EJB

    You configure security in the EJB using the @SecurityDomain and @RolesAllowed annotations. The following EJB code example limits access to the other security domain by users in the guest role.
    package example.ejb3;
    
    import java.security.Principal;
    
    import javax.annotation.Resource;
    import javax.annotation.security.RolesAllowed;
    import javax.ejb.SessionContext;
    import javax.ejb.Stateless;
    
    import org.jboss.ejb3.annotation.SecurityDomain;
    
    /**
     * Simple secured EJB using EJB security annotations
     * Allow access to "other" security domain by users in a "guest" role.
     */
    @Stateless
    @RolesAllowed({ "guest" })
    @SecurityDomain("other")
    public class SecuredEJB {
    
       // Inject the Session Context
       @Resource
       private SessionContext ctx;
    
       /**
        * Secured EJB method using security annotations
        */
       public String getSecurityInfo() {
          // Session context injected using the resource annotation
          Principal principal = ctx.getCallerPrincipal();
          return principal.toString();
       }
    }
    For more code examples, see the ejb-security quickstart in the JBoss EAP 6 Quickstarts bundle, which is available from the Red Hat Customer Portal.

    Note

    The security domain for an EJB can also be set using the jboss-ejb3.xml deployment descriptor. See Section 8.8.4, “jboss-ejb3.xml Deployment Descriptor Reference” for details.

Procedure 18.2. Configure JBoss EAP 6 to access custom principal in EJB 3 bean

  1. Configure the ApplicationRealm to defer to JAAS:
    <security-realm name="MyDomainRealm">
     <authentication>
       <jaas name="my-security-domain"/>
    </security-realm>
  2. Configure the JAAS security-domain to use the custom principal:
    <security-domain name="my-security-domain" cache-type="default">
       <authentication>
           <login-module code="UsersRoles" flag="required">
               <module-option name="usersProperties" value="file:///${jboss.server.config.dir}/users.properties"/>
               <module-option name="rolesProperties" value="file:///${jboss.server.config.dir}/roles.properties"/>
               <module-option name="principalClass" value="org.jboss.example.CustomPrincipalImpl"/>
           </login-module>
       </authentication>
    </security-domain>
  3. Deploy the custom principal as a JBoss module.
  4. Configure the org.jboss.as.remoting module (modules/org/jboss/as/remoting/main/module.xml) to depend on the module that contains the custom principal:
                
    <resources>
        <resource-root path="jboss-as-remoting-7.1.2.Final-redhat-1.jar"/>
        <!-- Insert resources here -->
    </resources>
    
    <dependencies>
        <module name="org.jboss.staxmapper"/>
        <module name="org.jboss.as.controller"/>
        <module name="org.jboss.as.domain-management"/>
        <module name="org.jboss.as.network"/>
        <module name="org.jboss.as.protocol"/>
        <module name="org.jboss.as.server"/>
        <module name="org.jboss.as.security" optional="true"/>
        <module name="org.jboss.as.threads"/>
        <module name="org.jboss.logging"/>
        <module name="org.jboss.modules"/>
        <module name="org.jboss.msc"/>        
        <module name="org.jboss.remoting3"/>
        <module name="org.jboss.sasl"/>
        <module name="org.jboss.threads"/>
        <module name="org.picketbox" optional="true"/>        
        <module name="javax.api" />
        <module name="org.jboss.example" />  <!--FIXME:  dependency on custom principal added here -->
    </dependencies>
  5. Configure the client to use org.jboss.ejb.client.naming, the jboss-ejb-client.properties file should look like the following:
    remote.connections=default
    endpoint.name=client-endpoint
    remote.connection.default.port=4447
    remote.connection.default.host=localhost
    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
    # The following setting is required when deferring to JAAS
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
    
    remote.connection.default.username=admin
    remote.connection.default.password=testing

18.2.9. Use Role-Based Security In Servlets

To add security to a servlet, you map each servlet to a URL pattern, and create security constraints on the URL patterns which need to be secured. The security constraints limit access to the URLs to roles. The authentication and authorization are handled by the security domain specified in the WAR's jboss-web.xml.
Prerequisites

Before you use role-based security in a servlet, the security domain used to authenticate and authorize access needs to be configured in the JBoss EAP 6 container.

Procedure 18.3. Add Role-Based Security to Servlets

  1. Add mappings between servlets and URL patterns.

    Use <servlet-mapping> elements in the web.xml to map individual servlets to URL patterns. The following example maps the servlet called DisplayOpResult to the URL pattern /DisplayOpResult.
    <servlet-mapping>
        <servlet-name>DisplayOpResult</servlet-name>
        <url-pattern>/DisplayOpResult</url-pattern>
    </servlet-mapping>		
    
    
  2. Add security constraints to the URL patterns.

    To map the URL pattern to a security constraint, use a <security-constraint>. The following example constrains access from the URL pattern /DisplayOpResult to be accessed by principals with the role eap_admin. The role needs to be present in the security domain.
    <security-constraint>
    	<display-name>Restrict access to role eap_admin</display-name>
    	<web-resource-collection>
    		<web-resource-name>Restrict access to role eap_admin</web-resource-name>
    		<url-pattern>/DisplayOpResult/*</url-pattern>
    	</web-resource-collection>
    	<auth-constraint>
    		<role-name>eap_admin</role-name>
    	</auth-constraint>	
    </security-constraint>	
    
    <security-role>
      <role-name>eap_admin</role-name>
    </security-role>
    
    
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
    
    
    You need to specify the authentication method, which can be any of the following: BASIC, FORM, DIGEST, CLIENT-CERT, SPNEGO. This example uses BASIC authentication.
  3. Specify the security domain in the WAR's jboss-web.xml

    Add the security domain to the WAR's jboss-web.xml in order to connect the servlets to the configured security domain, which knows how to authenticate and authorize principals against the security constraints. The following example uses the security domain called acme_domain.
    <jboss-web>
    	...
    	<security-domain>acme_domain</security-domain>
    	...
    </jboss-web>
    
    

Example 18.1. Example web.xml with Role-Based Security Configured

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

<display-name>Use Role-Based Security In Servlets</display-name>

<welcome-file-list>
  <welcome-file>/index.jsp</welcome-file>
</welcome-file-list>

<servlet-mapping>
    <servlet-name>DisplayOpResult</servlet-name>
    <url-pattern>/DisplayOpResult</url-pattern>
</servlet-mapping>

<security-constraint>
  <display-name>Restrict access to role eap_admin</display-name>
    <web-resource-collection>
      <web-resource-name>Restrict access to role eap_admin</web-resource-name>
      <url-pattern>/DisplayOpResult/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <role-name>eap_admin</role-name>
      </auth-constraint>
    </security-constraint>

    <security-role>
      <role-name>eap_admin</role-name>
    </security-role>

    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>

</web-app>

18.2.10. Use A Third-Party Authentication System In Your Application

You can integrate third-party security systems with JBoss EAP 6. These types of systems are usually token-based. The external system performs the authentication and passes a token back to the Web application through the request headers. This is often referred to as perimeter authentication. To configure perimeter authentication in your application, add a custom authentication valve. If you have a valve from a third-party provider, be sure it is in your classpath and follow the examples below, along with the documentation for your third-party authentication module.

Note

The location for configuring valves has changed in JBoss EAP 6. There is no longer a context.xml deployment descriptor. Valves are configured directly in the jboss-web.xml descriptor instead. The context.xml is now ignored.

Example 18.2. Basic Authentication Valve

<jboss-web>
  <valve>
    <class-name>org.jboss.security.negotiation.NegotiationAuthenticator</class-name>
  </valve>
</jboss-web>
This valve is used for Kerberos-based SSO. It also shows the most simple pattern for specifying a third-party authenticator for your Web application.

Example 18.3. Custom Valve With Header Attributes Set

<jboss-web>
  <valve>
    <class-name>org.jboss.web.tomcat.security.GenericHeaderAuthenticator</class-name>
    <param>
      <param-name>httpHeaderForSSOAuth</param-name>
      <param-value>sm_ssoid,ct-remote-user,HTTP_OBLIX_UID</param-value>
    </param>
    <param>
      <param-name>sessionCookieForSSOAuth</param-name>
      <param-value>SMSESSION,CTSESSION,ObSSOCookie</param-value>
    </param>
  </valve>
</jboss-web>
This example shows how to set custom attributes on your valve. The authenticator checks for the presence of the header ID and the session key, and passes them into the JAAS framework which drives the security layer, as the username and password value. You need a custom JAAS login module which can process the username and password and populate the subject with the correct roles. If no header values match the configured values, regular form-based authentication semantics apply.
Writing a Custom Authenticator

Writing your own authenticator is out of scope of this document. However, the following Java code is provided as an example.

Example 18.4. GenericHeaderAuthenticator.java

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
 
package org.jboss.web.tomcat.security;

import java.io.IOException;
import java.security.Principal;
import java.util.StringTokenizer;

import javax.management.JMException;
import javax.management.ObjectName;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.Realm;
import org.apache.catalina.Session;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.LoginConfig;
import org.jboss.logging.Logger;

import org.jboss.as.web.security.ExtendedFormAuthenticator;

/**
 * JBAS-2283: Provide custom header based authentication support
 * 
 * Header Authenticator that deals with userid from the request header Requires
 * two attributes configured on the Tomcat Service - one for the http header
 * denoting the authenticated identity and the other is the SESSION cookie
 * 
 * @author <a href="mailto:Anil.Saldhana@jboss.org">Anil Saldhana</a>
 * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
 * @version $Revision$
 * @since Sep 11, 2006
 */
public class GenericHeaderAuthenticator extends ExtendedFormAuthenticator {
  protected static Logger log = Logger
      .getLogger(GenericHeaderAuthenticator.class);

  protected boolean trace = log.isTraceEnabled();

  // JBAS-4804: GenericHeaderAuthenticator injection of ssoid and
  // sessioncookie name.
  private String httpHeaderForSSOAuth = null;

  private String sessionCookieForSSOAuth = null;

  /**
   * <p>
   * Obtain the value of the <code>httpHeaderForSSOAuth</code> attribute. This
   * attribute is used to indicate the request header ids that have to be
   * checked in order to retrieve the SSO identity set by a third party
   * security system.
   * </p>
   * 
   * @return a <code>String</code> containing the value of the
   *         <code>httpHeaderForSSOAuth</code> attribute.
   */
  public String getHttpHeaderForSSOAuth() {
    return httpHeaderForSSOAuth;
  }

  /**
   * <p>
   * Set the value of the <code>httpHeaderForSSOAuth</code> attribute. This
   * attribute is used to indicate the request header ids that have to be
   * checked in order to retrieve the SSO identity set by a third party
   * security system.
   * </p>
   * 
   * @param httpHeaderForSSOAuth
   *            a <code>String</code> containing the value of the
   *            <code>httpHeaderForSSOAuth</code> attribute.
   */
  public void setHttpHeaderForSSOAuth(String httpHeaderForSSOAuth) {
    this.httpHeaderForSSOAuth = httpHeaderForSSOAuth;
  }

  /**
   * <p>
   * Obtain the value of the <code>sessionCookieForSSOAuth</code> attribute.
   * This attribute is used to indicate the names of the SSO cookies that may
   * be present in the request object.
   * </p>
   * 
   * @return a <code>String</code> containing the names (separated by a
   *         <code>','</code>) of the SSO cookies that may have been set by a
   *         third party security system in the request.
   */
  public String getSessionCookieForSSOAuth() {
    return sessionCookieForSSOAuth;
  }

  /**
   * <p>
   * Set the value of the <code>sessionCookieForSSOAuth</code> attribute. This
   * attribute is used to indicate the names of the SSO cookies that may be
   * present in the request object.
   * </p>
   * 
   * @param sessionCookieForSSOAuth
   *            a <code>String</code> containing the names (separated by a
   *            <code>','</code>) of the SSO cookies that may have been set by
   *            a third party security system in the request.
   */
  public void setSessionCookieForSSOAuth(String sessionCookieForSSOAuth) {
    this.sessionCookieForSSOAuth = sessionCookieForSSOAuth;
  }

  /**
   * <p>
   * Creates an instance of <code>GenericHeaderAuthenticator</code>.
   * </p>
   */
  public GenericHeaderAuthenticator() {
    super();
  }

  public boolean authenticate(Request request, HttpServletResponse response,
      LoginConfig config) throws IOException {
    log.trace("Authenticating user");

    Principal principal = request.getUserPrincipal();
    if (principal != null) {
      if (trace)
        log.trace("Already authenticated '" + principal.getName() + "'");
      return true;
    }

    Realm realm = context.getRealm();
    Session session = request.getSessionInternal(true);

    String username = getUserId(request);
    String password = getSessionCookie(request);

    // Check if there is sso id as well as sessionkey
    if (username == null || password == null) {
      log.trace("Username is null or password(sessionkey) is null:fallback to form auth");
      return super.authenticate(request, response, config);
    }
    principal = realm.authenticate(username, password);

    if (principal == null) {
      forwardToErrorPage(request, response, config);
      return false;
    }

    session.setNote(Constants.SESS_USERNAME_NOTE, username);
    session.setNote(Constants.SESS_PASSWORD_NOTE, password);
    request.setUserPrincipal(principal);

    register(request, response, principal, HttpServletRequest.FORM_AUTH,
        username, password);
    return true;
  }

  /**
   * Get the username from the request header
   * 
   * @param request
   * @return
   */
  protected String getUserId(Request request) {
    String ssoid = null;
    // We can have a comma-separated ids
    String ids = "";
    try {
      ids = this.getIdentityHeaderId();
    } catch (JMException e) {
      if (trace)
        log.trace("getUserId exception", e);
    }
    if (ids == null || ids.length() == 0)
      throw new IllegalStateException(
          "Http headers configuration in tomcat service missing");

    StringTokenizer st = new StringTokenizer(ids, ",");
    while (st.hasMoreTokens()) {
      ssoid = request.getHeader(st.nextToken());
      if (ssoid != null)
        break;
    }
    if (trace)
      log.trace("SSOID-" + ssoid);
    return ssoid;
  }

  /**
   * Obtain the session cookie from the request
   * 
   * @param request
   * @return
   */
  protected String getSessionCookie(Request request) {
    Cookie[] cookies = request.getCookies();
    log.trace("Cookies:" + cookies);
    int numCookies = cookies != null ? cookies.length : 0;

    // We can have comma-separated ids
    String ids = "";
    try {
      ids = this.getSessionCookieId();
      log.trace("Session Cookie Ids=" + ids);
    } catch (JMException e) {
      if (trace)
        log.trace("checkSessionCookie exception", e);
    }
    if (ids == null || ids.length() == 0)
      throw new IllegalStateException(
          "Session cookies configuration in tomcat service missing");

    StringTokenizer st = new StringTokenizer(ids, ",");
    while (st.hasMoreTokens()) {
      String cookieToken = st.nextToken();
      String val = getCookieValue(cookies, numCookies, cookieToken);
      if (val != null)
        return val;
    }
    if (trace)
      log.trace("Session Cookie not found");
    return null;
  }

  /**
   * Get the configured header identity id in the tomcat service
   * 
   * @return
   * @throws JMException
   */
  protected String getIdentityHeaderId() throws JMException {
    if (this.httpHeaderForSSOAuth != null)
      return this.httpHeaderForSSOAuth;
    return (String) mserver.getAttribute(new ObjectName(
        "jboss.web:service=WebServer"), "HttpHeaderForSSOAuth");
  }

  /**
   * Get the configured session cookie id in the tomcat service
   * 
   * @return
   * @throws JMException
   */
  protected String getSessionCookieId() throws JMException {
    if (this.sessionCookieForSSOAuth != null)
      return this.sessionCookieForSSOAuth;
    return (String) mserver.getAttribute(new ObjectName(
        "jboss.web:service=WebServer"), "SessionCookieForSSOAuth");
  }

  /**
   * Get the value of a cookie if the name matches the token
   * 
   * @param cookies
   *            array of cookies
   * @param numCookies
   *            number of cookies in the array
   * @param token
   *            Key
   * @return value of cookie
   */
  protected String getCookieValue(Cookie[] cookies, int numCookies,
      String token) {
    for (int i = 0; i < numCookies; i++) {
      Cookie cookie = cookies[i];
      log.trace("Matching cookieToken:" + token + " with cookie name="
          + cookie.getName());
      if (token.equals(cookie.getName())) {
        if (trace)
          log.trace("Cookie-" + token + " value=" + cookie.getValue());
        return cookie.getValue();
      }
    }
    return null;
  }
}