Jakarta EE Security: Advanced Topics

This chapter provides advanced information on securing Jakarta EE applications.

Working with Digital Certificates

Digital certificates for GlassFish Server have already been generated and can be found in the directory domain-dir/config/. These digital certificates are self-signed and are intended for use in a development environment; they are not intended for production purposes. For production purposes, generate your own certificates and have them signed by a Certificate Authority (CA).

To use the Secure Sockets Layer (SSL), an application or web server must have an associated certificate for each external interface, or IP address, that accepts secure connections. The theory behind this design is that a server should provide some kind of reasonable assurance that its owner is who you think it is, particularly before receiving any sensitive information. It may be useful to think of a certificate as a "digital driver’s license" for an Internet address. The certificate states which company the site is associated with, along with some basic contact information about the site owner or administrator.

The digital certificate is cryptographically signed by its owner and is difficult for anyone else to forge. For sites involved in e-commerce or in any other business transaction in which authentication of identity is important, a certificate can be purchased from a well-known CA such as VeriSign or Thawte. If your server certificate is self-signed, you must install it in the GlassFish Server keystore file (keystore.jks). If your client certificate is self-signed, you should install it in the GlassFish Server truststore file (cacerts.jks).

Sometimes, authentication is not really a concern. For example, an administrator might simply want to ensure that data being transmitted and received by the server is private and cannot be snooped by anyone eavesdropping on the connection. In such cases, you can save the time and expense involved in obtaining a CA certificate and simply use a self-signed certificate.

SSL uses public-key cryptography, which is based on key pairs. Key pairs contain one public key and one private key. Data encrypted with one key can be decrypted only with the other key of the pair. This property is fundamental to establishing trust and privacy in transactions. For example, using SSL, the server computes a value and encrypts it by using its private key. The encrypted value is called a digital signature. The client decrypts the encrypted value by using the server’s public key and compares the value to its own computed value. If the two values match, the client can trust that the signature is authentic, because only the private key could have been used to produce such a signature.

Digital certificates are used with HTTPS to authenticate web clients. The HTTPS service of most web servers will not run unless a digital certificate has been installed. Use the procedure outlined in the next section, Creating a Server Certificate, to set up a digital certificate that can be used by your application or web server to enable SSL.

One tool that can be used to set up a digital certificate is keytool, a key and certificate management utility that ships with the JDK. This tool enables users to administer their own public/private key pairs and associated certificates for use in self-authentication, whereby the user authenticates himself or herself to other users or services, or data integrity and authentication services, using digital signatures. The tool also allows users to cache the public keys, in the form of certificates, of their communicating peers.

For a better understanding of keytool and public-key cryptography, see Further Information about Advanced Security Topics for a link to the keytool documentation.

Creating a Server Certificate

A server certificate has already been created for GlassFish Server and can be found in the domain-dir/config/ directory. The server certificate is in keystore.jks. The cacerts.jks file contains all the trusted certificates, including client certificates.

If necessary, you can use keytool to generate certificates. The keytool utility stores the keys and certificates in a file termed a keystore, a repository of certificates used for identifying a client or a server. Typically, a keystore is a file that contains one client’s or one server’s identity. The keystore protects private keys by using a password.

If you don’t specify a directory when specifying the keystore file name, the keystores are created in the directory from which the keytool command is run. This can be the directory where the application resides, or it can be a directory common to many applications.

The general steps for creating a server certificate are as follows.

  1. Create the keystore.

  2. Export the certificate from the keystore.

  3. Sign the certificate.

  4. Import the certificate into a truststore: a repository of certificates used for verifying the certificates. A truststore typically contains more than one certificate.

The next section provides specific information on using the keytool utility to perform these steps.

To Use keytool to Create a Server Certificate

Run keytool to generate a new key pair in the default development keystore file, keystore.jks. This example uses the alias server-alias to generate a new public/private key pair and wrap the public key into a self-signed certificate inside keystore.jks. The key pair is generated by using an algorithm of type RSA, with a default password of changeit. For more information and other examples of creating and managing keystore files, read the keytool documentation.

RSA is public-key encryption technology developed by RSA Data Security, Inc.

From the directory in which you want to create the key pair, run keytool as shown in the following steps.

  1. Generate the server certificate.

    Enter the keytool command all on one line:

    java-home/bin/keytool -genkey -alias server-alias -keyalg RSA
    -keypass changeit -storepass changeit -keystore keystore.jks

    When you press Enter, keytool prompts you to enter the server name, organizational unit, organization, locality, state, and country code.

    You must enter the server name in response to keytool's first prompt, in which it asks for first and last names. For testing purposes, this can be localhost.

  2. Export the generated server certificate in keystore.jks into the file server.cer.

    Enter the keytool command all on one line:

    java-home/bin/keytool -export -alias server-alias -storepass changeit
    -file server.cer -keystore keystore.jks
  3. If you want to have the certificate signed by a CA, read the example in the keytool documentation.

  4. To add the server certificate to the truststore file, cacerts.jks, run keytool from the directory where you created the keystore and server certificate.

    Use the following parameters:

    java-home/bin/keytool -import -v -trustcacerts -alias server-alias
    -file server.cer -keystore cacerts.jks -keypass changeit
    -storepass changeit

    Information on the certificate, such as that shown next, will appear:

    Owner: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US
    Issuer: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US
    Serial number: 3e932169
    Valid from: Mon Nov 26 18:15:47 EST 2012 until: Sun Feb 24 18:15:47 EST 2013
    Certificate fingerprints:
             MD5: 52:9F:49:68:ED:78:6F:39:87:F3:98:B3:6A:6B:0F:90
             SHA1: EE:2E:2A:A6:9E:03:9A:3A:1C:17:4A:28:5E:97:20:78:3F:
             SHA256: 80:05:EC:7E:50:50:5D:AA:A3:53:F1:11:9B:19:EB:0D:20:67:C1:12:
    AF:42:EC:CD:66:8C:BD:99:AD:D9:76:95
             Signature algorithm name: SHA256withRSA         Version: 3
             ...
    Trust this certificate? [no]:
  5. Enter yes, then press the Enter or Return key.

    The following information appears:

    Certificate was added to keystore
    [Storing cacerts.jks]

Adding Users to the Certificate Realm

In the certificate realm, user identity is set up in the GlassFish Server security context and populated with user data obtained from cryptographically verified client certificates. For step-by-step instructions for creating this type of certificate, see Working with Digital Certificates.

Using a Different Server Certificate with GlassFish Server

Follow the steps in Creating a Server Certificate to create your own server certificate, have it signed by a CA, and import the certificate into keystore.jks.

Make sure that when you create the certificate, you follow these rules.

  • When you create the server certificate, keytool prompts you to enter your first and last name. In response to this prompt, you must enter the name of your server. For testing purposes, this can be localhost.

  • If you want to replace the existing keystore.jks, you must either change your keystore’s password to the default password (changeit) or change the default password to your keystore’s password.

To Specify a Different Server Certificate

To specify that GlassFish Server should use the new keystore for authentication and authorization decisions, you must set the JVM options for GlassFish Server so that they recognize the new keystore. To use a different keystore from the one provided for development purposes, follow these steps.

  1. Start GlassFish Server if you haven’t already done so. Information on starting the GlassFish Server can be found in Starting and Stopping GlassFish Server.

  2. Open the GlassFish Server Administration Console in a web browser at http://localhost:4848.

  3. Expand Configurations, then expand server-config, then click JVM Settings.

  4. Click the JVM Options tab.

  5. Change the following JVM options so that they point to the location and name of the new keystore. The current settings are shown below:

    -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks
    -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks
  6. If you’ve changed the keystore password from its default value, you need to add the password option as well:

    -Djavax.net.ssl.keyStorePassword=your-new-password
  7. Click Save, then restart GlassFish Server.

Authentication Mechanisms

This section discusses the client authentication and mutual authentication mechanisms.

Client Authentication

With client authentication, the web server authenticates the client by using the client’s public key certificate. Client authentication is a more secure method of authentication than either basic or form-based authentication. It uses HTTP over SSL (HTTPS), in which the server authenticates the client using the client’s public key certificate. SSL technology provides data encryption, server authentication, message integrity, and optional client authentication for a TCP/IP connection. You can think of a public key certificate as the digital equivalent of a passport. The certificate is issued by a trusted organization, a certificate authority (CA), and provides identification for the bearer.

Before using client authentication, make sure that the client has a valid public key certificate. For more information on creating and using public key certificates, read Working with Digital Certificates.

The following example shows how to declare client authentication in your deployment descriptor:

<login-config>
    <auth-method>CLIENT-CERT</auth-method>
</login-config>

Jakarta Security provides an alternative means to configure client authentication using the HttpAuthenticationMechanism interface. This interface defines an SPI for writing authentication mechanisms that can be provided with an application and deployed using CDI. See Overview of the HTTP Authentication Mechanism Interface.

Mutual Authentication

With mutual authentication, the server and the client authenticate each other. Mutual authentication is of two types:

When using certificate-based mutual authentication, the following actions occur.

  1. A client requests access to a protected resource.

  2. The web server presents its certificate to the client.

  3. The client verifies the server’s certificate.

  4. If successful, the client sends its certificate to the server.

  5. The server verifies the client’s credentials.

  6. If successful, the server grants access to the protected resource requested by the client.

Figure 1, “Certificate-Based Mutual Authentication” shows what occurs during certificate-based mutual authentication.

Diagram of six steps in mutual authentication with certificates
Figure 1. Certificate-Based Mutual Authentication

In user name/password-based mutual authentication, the following actions occur.

  1. A client requests access to a protected resource.

  2. The web server presents its certificate to the client.

  3. The client verifies the server’s certificate.

  4. If successful, the client sends its user name and password to the server.

  5. The server verifies the client’s credentials

  6. If the verification is successful, the server grants access to the protected resource requested by the client.

Figure 2, “User Name/Password-Based Mutual Authentication” shows what occurs during user name/password-based mutual authentication.

Diagram of five steps in mutual authentication with user name and password
Figure 2. User Name/Password-Based Mutual Authentication

Enabling Mutual Authentication over SSL

This section discusses setting up client-side authentication. Enabling both server-side and client-side authentication is called mutual, or two-way, authentication. In client authentication, clients are required to submit certificates issued by a certificate authority that you choose to accept.

There are at least two ways to enable mutual authentication over SSL.

  • The preferred method is to set the method of authentication in the web.xml application deployment descriptor to CLIENT-CERT. This enforces mutual authentication by modifying the deployment descriptor of the given application. In this way, client authentication is enabled only for a specific resource controlled by the security constraint, and the check is performed only when the application requires client authentication.

  • A less commonly used method is to set the clientAuth property in the certificate realm to true if you want the SSL stack to require a valid certificate chain from the client before accepting a connection. A false value (which is the default) will not require a certificate chain unless the client requests a resource protected by a security constraint that uses CLIENT-CERT authentication. When you enable client authentication by setting the clientAuth property to true, client authentication will be required for all the requests going through the specified SSL port. If you turn clientAuth on, it is on all of the time, which can severely degrade performance.

When client authentication is enabled in both of these ways, client authentication will be performed twice.

Creating a Client Certificate for Mutual Authentication

If you have a certificate signed by a trusted Certificate Authority (CA) such as Verisign, and the GlassFish Server cacerts.jks file already contains a certificate verified by that CA, you do not need to complete this step. You need to install your certificate in the GlassFish Server certificate file only when your certificate is self-signed.

From the directory where you want to create the client certificate, run keytool as outlined here. When you press Enter, keytool prompts you to enter the server name, organizational unit, organization, locality, state, and country code.

You must enter the server name in response to keytool's first prompt, in which it asks for first and last names. For testing purposes, this can be localhost. If this example is to verify mutual authentication and you receive a runtime error stating that the HTTPS host name is wrong, re-create the client certificate, being sure to use the same host name you will use when running the example. For example, if your machine name is duke, then enter duke as the certificate CN or when prompted for first and last names. When accessing the application, enter a URL that points to the same location (for example, https://duke:8181/mutualauth/hello). This is necessary because during SSL handshake, the server verifies the client certificate by comparing the certificate name to the host name from which it originates.

To create a keystore named client_keystore.jks that contains a client certificate named client.cer, follow these steps.

  1. Create a backup copy of the server truststore file. To do this,

    1. Change to the directory containing the server’s keystore and truststore files, domain-dir\config.

    2. Copy cacerts.jks to cacerts.backup.jks.

    3. Copy keystore.jks to keystore.backup.jks.

      Do not put client certificates in the cacerts.jks file. Any certificate you add to the cacerts file effectively can be a trusted root for any and all certificate chains. After you have completed development, delete the development version of the cacerts file and replace it with the original copy.

  2. Generate the client certificate. Enter the following command from the directory where you want to generate the client certificate:

    java-home/bin/keytool -genkey -alias client-alias -keyalg RSA -keypass changeit -storepass changeit -keystore client_keystore.jks
  3. Export the generated client certificate into the file client.cer:

    java-home/bin/keytool -export -alias client-alias -storepass changeit -file client.cer -keystore client_keystore.jks
  4. Add the certificate to the truststore file domain-dir/config/cacerts.jks. Run keytool from the directory where you created the keystore and client certificate. Use the following parameters:

    java-home/bin/keytool -import -v -trustcacerts -alias client-alias
    -file client.cer -keystore domain-dir/config/cacerts.jks
    -keypass changeit -storepass changeit

    The keytool utility returns a message like this one:

    Owner: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US
    Issuer: CN=localhost, OU=My Company, O=Software, L=Santa Clara, ST=CA, C=US
    Serial number: 3e39e66a
    Valid from: Tue Nov 27 12:22:47 EST 2012 until: Mon Feb 25 12:22:47 EST 2013
    Certificate fingerprints:
        MD5: 5A:B0:4C:88:4E:F8:EF:E9:E5:8B:53:BD:D0:AA:8E:5A
        SHA1:90:00:36:5B:E0:A7:A2:BD:67:DB:EA:37:B9:61:3E:26:B3:89:46:32
        Signature algorithm name: SHA1withRSA
        Version: 3
    Trust this certificate? [no]: yes
    Certificate was added to keystore
    [Storing cacerts.jks]
  5. Restart GlassFish Server.

Using the JDBC Realm for User Authentication

An authentication realm, sometimes called a security policy domain or security domain, is a scope over which an application server defines and enforces a common security policy. A realm contains a collection of users, who may or may not be assigned to a group. GlassFish Server comes preconfigured with the file, certificate, and administration realms. An administrator can also set up LDAP, JDBC, digest, or custom realms.

An application can specify in its deployment descriptor which realm to use. If the application does not specify a realm, GlassFish Server uses its default realm, the file realm. If an application specifies that a JDBC realm is to be used for user authentication, GlassFish Server will retrieve user credentials from a database. The application server uses the database information and the enabled JDBC realm option in the configuration file.

A database provides an easy way to add, edit, or delete users at runtime and enables users to create their own accounts without any administrative assistance. Using a database has an additional benefit: providing a place to securely store any extra user information. A realm can be thought of as a database of user names and passwords that identify valid users of a web application or set of web applications with an enumeration of the list of roles associated with each valid user. Access to specific web application resources is granted to all users in a particular role, instead of enumerating a list of associated users. A user name can have any number of roles associated with it.

Two of the tutorial case studies, Duke’s Tutoring Case Study Example and Duke’s Forest Case Study Example use a JDBC realm for user authentication.

To Configure a JDBC Authentication Realm

GlassFish Server enables administrators to specify a user’s credentials (user name and password) in the JDBC realm instead of in the connection pool. This prevents other applications from browsing the database tables for user credentials. By default, storing passwords as clear text is not supported in the JDBC realm. Under normal circumstances, passwords should not be stored as clear text.

  1. Create the database tables in which user credentials for the realm will be stored.

  2. Add user credentials to the database tables you created.

  3. Create a JDBC connection pool for the database.

    You can use the Administration Console or the command line to create a connection pool.

  4. Create a JDBC resource for the database.

    You can use the Administration Console or the command line to create a JDBC resource.

  5. Create a realm.

    This step needs to associate the resource with the realm, define the tables and columns for users and groups used for authentication, and define the digest algorithm that will be used for storing passwords in the database.

    You can use the Administration Console or the command line to create a realm.

  6. Modify the deployment descriptor for your application to specify the JDBC realm.

    • For an enterprise application in an EAR file, modify the glassfish-application.xml file.

    • For a web application in a WAR file, modify the web.xml file.

    • For an enterprise bean in an EJB JAR file, modify the glassfish-ejb-jar.xml file.

      For example, for a hypothetical application, the web.xml file could specify the jdbcRealm realm, as follows:

      <login-config>
          <auth-method>FORM</auth-method>
          <realm-name>jdbcRealm</realm-name>
          <form-login-config>
              <form-login-page>/login.xhtml</form-login-page>
              <form-error-page>/login.xhtml</form-error-page>
          </form-login-config>
      </login-config>
      <security-constraint>
          <web-resource-collection>
              <web-resource-name>Secure Pages</web-resource-name>
              <description/>
              <url-pattern>/admin/*</url-pattern>
          </web-resource-collection>
          <auth-constraint>
              <role-name>ADMINS</role-name>
          </auth-constraint>
      </security-constraint>

      Form-based login is specified for all web pages under /admin. Access to those pages will be allowed only to users in the ADMINS role.

  7. Assign security roles to users or groups of users in the realm.

    To assign a security role to a group or to a user, add a security-role-mapping element to the application server-specific deployment descriptor, in this case glassfish-web.xml:

    <security-role-mapping>
        <role-name>USERS</role-name>
        <group-name>USERS</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>ADMINS</role-name>
        <group-name>ADMINS</group-name>
    </security-role-mapping>

    Since GlassFish Server users are assigned to groups during the user creation process, this is more efficient than mapping security roles to individual users.

Securing HTTP Resources

When a request URI is matched by multiple constrained URL patterns, the constraints that apply to the request are those that are associated with the best matching URL pattern. The servlet matching rules defined in Chapter 12, "Mapping Requests To Servlets" in the Jakarta Servlet 5.0 Specification, are used to determine the best matching URL pattern to the request URI. No protection requirements apply to a request URI that is not matched by a constrained URL pattern. The HTTP method of the request plays no role in selecting the best matching URL pattern for a request.

When HTTP methods are listed within a constraint definition, the protections defined by the constraint are applied to the listed methods only.

When HTTP methods are not listed within a constraint definition, the protections defined by the constraint apply to the complete set of HTTP methods, including HTTP extension methods.

When constraints with different protection requirements apply to the same combination of URL patterns and HTTP methods, the rules for combining the protection requirements are as defined in Section 13.8.1, "Combining Constraints" in the Jakarta Servlet 5.0 Specification.

Follow these guidelines to properly secure a web application.

  • Do not list HTTP methods within constraint definitions. This is the simplest way to ensure that you are not leaving HTTP methods unprotected. For example:

    <!-- SECURITY CONSTRAINT #1 -->
    <security-constraint>
        <display-name>Do not enumerate Http Methods</display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>sales</role-name>
        </auth-constraint>
    </security-constraint>

    If you list methods in a constraint, all non-listed methods of the effectively infinite set of possible HTTP methods, including extension methods, will be unprotected. Use such a constraint only if you are certain that this is the protection scheme you intend to define. The following example shows a constraint that lists the GET method and thus defines no protection on any of the other possible HTTP methods:

    <!-- SECURITY CONSTRAINT #2 -->
    <security-constraint>
        <display-name>
            Protect GET only, leave all other methods unprotected
        </display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>sales</role-name>
        </auth-constraint>
    </security-constraint>
  • If you need to apply specific types of protection to specific HTTP methods, make sure that you define constraints to cover every method that you want to permit, with or without constraint, at the corresponding URL patterns. If there are any methods that you do not want to permit, you must also create a constraint that denies access to those methods at the same patterns; for an example, see security constraint #5 in the next bullet.

    For example, to permit GET and POST, where POST requires authentication and GET is permitted without constraint, you could define the following constraints:

    <!-- SECURITY CONSTRAINT #3 -->
    <security-constraint>
        <display-name>Allow unprotected GET</display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>
    </security-constraint>
    
    <!-- SECURITY CONSTRAINT #4 -->
    <security-constraint>
        <display-name>Require authentication for POST</display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>sales</role-name>
        </auth-constraint>
    </security-constraint>
  • The simplest way to ensure that you deny all HTTP methods except those that you want to be permitted is to use http-method-omission elements to omit those HTTP methods from the security constraint, and also to define an auth-constraint that names no roles. The security constraint will apply to all methods except those that were named in the omissions, and the constraint will apply only to the resources matched by the patterns in the constraint.

    For example, the following constraint excludes access to all methods except GET and POST at the resources matched by the pattern /company/*:

    <!-- SECURITY CONSTRAINT #5 -->
    <security-constraint>
        <display-name>Deny all HTTP methods except GET and POST</display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
            <http-method-omission>GET</http-method-omission>
            <http-method-omission>POST</http-method-omission>
        </web-resource-collection>
        <auth-constraint/>
    </security-constraint>

    If you want to extend these exclusions to the unconstrained parts of your application, also include the URL pattern / (forward slash):

    <!-- SECURITY CONSTRAINT #6 -->
    <security-constraint>
        <display-name>Deny all HTTP methods except GET and POST</display-name>
        <web-resource-collection>
            <url-pattern>/company/*</url-pattern>
            <url-pattern>/</url-pattern>
            <http-method-omission>GET</http-method-omission>
            <http-method-omission>POST</http-method-omission>
        </web-resource-collection>
        <auth-constraint/>
    </security-constraint>
  • If, for your web application, you do not want any resource to be accessible unless you explicitly define a constraint that permits access to it, you can define an auth-constraint that names no roles and associate it with the URL pattern /. The URL pattern / is the weakest matching pattern. Do not list any HTTP methods in this constraint:

    <!-- SECURITY CONSTRAINT #7 -->
    <security-constraint>
        <display-name>
            Switch from Constraint to Permission model
            (where everything is denied by default)
        </display-name>
        <web-resource-collection>
            <url-pattern>/</url-pattern>
        </web-resource-collection>
        <auth-constraint/>
    </security-constraint>

Securing Application Clients

The Jakarta EE authentication requirements for application clients are the same as for other Jakarta EE components, and the same authentication techniques can be used as for other Jakarta EE application components. No authentication is necessary when accessing unprotected web resources.

When accessing protected web resources, the usual varieties of authentication can be used: HTTP basic authentication, HTTP login-form authentication, or SSL client authentication. Specifying an Authentication Mechanism in the Deployment Descriptor describes how to specify HTTP basic authentication and HTTP login-form authentication. Client Authentication describes how to specify SSL client authentication.

Authentication is required when accessing protected enterprise beans. The authentication mechanisms for enterprise beans are discussed in Securing Enterprise Beans.

An application client makes use of an authentication service provided by the application client container for authenticating its users. The container’s service can be integrated with the native platform’s authentication system so that a single sign-on capability is used. The container can authenticate the user either when the application is started or when a protected resource is accessed.

An application client can provide a class, called a login module, to gather authentication data. If so, the jakarta.security.auth.callback.CallbackHandler interface must be implemented, and the class name must be specified in its deployment descriptor. The application’s callback handler must fully support Callback objects specified in the jakarta.security.auth.callback package.

Using Login Modules

An application client can use the Java Authentication and Authorization Service (JAAS) to create login modules for authentication. A JAAS-based application implements the jakarta.security.auth.callback.CallbackHandler interface so that it can interact with users to enter specific authentication data, such as user names or passwords, or to display error and warning messages.

Applications implement the CallbackHandler interface and pass it to the login context, which forwards it directly to the underlying login modules. A login module uses the callback handler both to gather input, such as a password or smart card PIN, from users and to supply information, such as status information, to users. Because the application specifies the callback handler, an underlying login module can remain independent of the various ways applications interact with users.

For example, the implementation of a callback handler for a GUI application might display a window to solicit user input, or the implementation of a callback handler for a command-line tool might simply prompt the user for input directly from the command line.

The login module passes an array of appropriate callbacks to the callback handler’s handle method, such as a NameCallback for the user name and a PasswordCallback for the password; the callback handler performs the requested user interaction and sets appropriate values in the callbacks. For example, to process a NameCallback, the CallbackHandler might prompt for a name, retrieve the value from the user, and call the setName method of the NameCallback to store the name.

For more information on using JAAS for authentication in login modules, refer to the documentation listed in Further Information about Advanced Security Topics.

Using Programmatic Login

Programmatic login enables the client code to supply user credentials. If you are using an enterprise bean client, you can use the com.sun.appserv.security.ProgrammaticLogin class with its convenient login and logout methods. Programmatic login is specific to a server.

Securing Enterprise Information Systems Applications

In Enterprise Information Systems (EIS) applications, components request a connection to an EIS resource.

Overview of Securing Enterprise Information Systems Applications

As part of this connection, the EIS can require a sign-on for the requester to access the resource. The application component provider has two choices for the design of the EIS sign-on.

  • Container-managed sign-on: The application component lets the container take the responsibility of configuring and managing the EIS sign-on. The container determines the user name and password for establishing a connection to an EIS instance.

  • Component-managed sign-on: The application component code manages EIS sign-on by including code that performs the sign-on process to an EIS.

You can also configure security for resource adapters. See Configuring Resource Adapter Security.

Container-Managed Sign-On

In container-managed sign-on, an application component does not have to pass any sign-on security information to the getConnection() method. The security information is supplied by the container, as shown in the following example (the method call is highlighted in bold):

// Business method in an application component
Context initctx = new InitialContext();
// Perform JNDI lookup to obtain a connection factory
jakarta.resource.cci.ConnectionFactory cxf =
    (jakarta.resource.cci.ConnectionFactory)initctx.lookup(
    "java:comp/env/eis/MainframeCxFactory");
// Invoke factory to obtain a connection. The security
// information is not passed in the getConnection method
jakarta.resource.cci.Connection cx = cxf.getConnection();
...

Component-Managed Sign-On

In component-managed sign-on, an application component is responsible for passing the needed sign-on security information for the resource to the getConnection method. For example, security information might be a user name and password, as shown here (the method call is highlighted in bold):

// Method in an application component
Context initctx = new InitialContext();

// Perform JNDI lookup to obtain a connection factory
jakarta.resource.cci.ConnectionFactory cxf =
    (jakarta.resource.cci.ConnectionFactory)initctx.lookup(
    "java:comp/env/eis/MainframeCxFactory");

// Get a new ConnectionSpec
com.myeis.ConnectionSpecImpl properties = //..

// Invoke factory to obtain a connection
properties.setUserName("...");
properties.setPassword("...");
jakarta.resource.cci.Connection cx =
    cxf.getConnection(properties);
...

Configuring Resource Adapter Security

A resource adapter is a system-level software component that typically implements network connectivity to an external resource manager. A resource adapter can extend the functionality of the Jakarta EE platform either by implementing one of the Jakarta EE standard service APIs, such as a JDBC driver, or by defining and implementing a resource adapter for a connector to an external application system. Resource adapters can also provide services that are entirely local, perhaps interacting with native resources. Resource adapters interface with the Jakarta EE platform through the Jakarta EE service provider interfaces (Jakarta EE SPI). A resource adapter that uses the Jakarta EE SPIs to attach to the Jakarta EE platform will be able to work with all Jakarta EE products.

To configure the security settings for a resource adapter, you need to edit the resource adapter descriptor file, ra.xml. Here is an example of the part of an ra.xml file that configures security properties for a resource adapter:

<authentication-mechanism>
    <authentication-mechanism-type>
        BasicPassword
    </authentication-mechanism-type>
    <credential-interface>
        jakarta.resource.spi.security.PasswordCredential
    </credential-interface>
</authentication-mechanism>
<reauthentication-support>false</reauthentication-support>

You can find out more about the options for configuring resource adapter security by reviewing as-install/lib/schemas/connector_2_0.xsd. You can configure the following elements in the resource adapter deployment descriptor file.

  • Authentication mechanisms: Use the authentication-mechanism element to specify an authentication mechanism supported by the resource adapter. This support is for the resource adapter, not for the underlying EIS instance.

    There are two supported mechanism types:

    • BasicPassword, which supports the following interface:

      jakarta.resource.spi.security.PasswordCredential
    • Kerbv5, which supports the following interface:

      jakarta.resource.spi.security.GenericCredential

      GlassFish Server does not currently support this mechanism type.

  • Reauthentication support: Use the reauthentication-support element to specify whether the resource adapter implementation supports reauthentication of existing Managed-Connection instances. Options are true or false.

  • Security permissions: Use the security-permission element to specify a security permission that is required by the resource adapter code. Support for security permissions is optional and is not supported in the current release of GlassFish Server. You can, however, manually update the server.policy file to add the relevant permissions for the resource adapter.

    The security permissions listed in the deployment descriptor are different from those required by the default permission set as specified in the connector specification.

    For more information on the implementation of the security permission specification, see the security policy file documentation listed in Further Information about Advanced Security Topics.

In addition to specifying resource adapter security in the ra.xml file, you can create a security map for a connector connection pool to map an application principal or a user group to a back-end EIS principal. The security map is usually used if one or more EIS back-end principals are used to execute operations (on the EIS) initiated by various principals or user groups in the application.

Mapping an Application Principal to EIS Principals

When using GlassFish Server, you can use security maps to map the caller identity of the application (principal or user group) to a suitable EIS principal in container-managed transaction-based scenarios. When an application principal initiates a request to an EIS, GlassFish Server first checks for an exact principal by using the security map defined for the connector connection pool to determine the mapped back-end EIS principal. If there is no exact match, GlassFish Server uses the wildcard character specification, if any, to determine the mapped back-end EIS principal. Security maps are used when an application user needs to execute an EIS operation that requires execution as a specific identity in the EIS.

To work with security maps, use the Administration Console. From the Administration Console, follow these steps to get to the security maps page.

  1. In the navigation tree, expand the Resources node.

  2. Expand the Connectors node.

  3. Select the Connector Connection Pools node.

  4. On the Connector Connection Pools page, click the name of the connection pool for which you want to create a security map.

  5. Click the Security Maps tab.

  6. Click New to create a new security map for the connection pool.

  7. Enter a name by which you will refer to the security map, as well as the other required information.

    Click Help for more information on the individual options.

Configuring Security Using Deployment Descriptors

The recommended way to configure security in the Jakarta EE 8 platform is with annotations. If you wish to override the security settings at deployment time, you can use security elements in the web.xml deployment descriptor to do so. This section describes how to use the deployment descriptor to specify basic authentication and to override default principal-to-role mapping.

Specifying Security for Basic Authentication in the Deployment Descriptor

The elements of the deployment descriptor that add basic authentication to an example tell the server or browser to perform the following tasks.

  • Send a standard login dialog box to collect user name and password data.

  • Verify that the user is authorized to access the application.

  • If authorized, display the servlet to the user.

The following sample code shows the security elements for a deployment descriptor that could be used in the example of basic authentication found in the jakartaee-examples/tutorial/security/hello2_basicauth/ directory:

    <security-constraint>
        <display-name>SecurityConstraint</display-name>
        <web-resource-collection>
             <web-resource-name>WRCollection</web-resource-name>
            <url-pattern>/greeting</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>TutorialUser</role-name>
        </auth-constraint>
        <user-data-constraint>
             <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>file</realm-name>
    </login-config>
    <security-role>
        <role-name>TutorialUser</role-name>
    </security-role>

This deployment descriptor specifies that the request URI /greeting can be accessed only by users who have entered their user names and passwords and have been authorized to access this URL because they have been verified to be in the role TutorialUser. The user name and password data will be sent over a protected transport in order to keep it from being read in transit.

Specifying Non-Default Principal-to-Role Mapping in the Deployment Descriptor

Jakarta Security requires that group principal names be mapped to roles of the same name by default. GlassFish adheres to this standard, by default, and provides group principal to role mapping. Implementations of the standard can, however, provide mechanisms to configure a different default.

To map a role name permitted by the application or module to principals (users) and groups defined on the server, use the security-role-mapping element in the runtime deployment descriptor file (glassfish-application.xml, glassfish-web.xml, or glassfish-ejb-jar.xml). The entry needs to declare a mapping between a security role used in the application and one or more groups or principals defined for the applicable realm of GlassFish Server. An example for the glassfish-web.xml file is shown below:

<glassfish-web-app>
    <security-role-mapping>
        <role-name>DIRECTOR</role-name>
        <principal-name>schwartz</principal-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>DEPT-ADMIN</role-name>
        <group-name>dept-admins</group-name>
    </security-role-mapping>
</glassfish-web-app>

The role name can be mapped to either a specific principal (user), a group, or both. The principal or group names referenced must be valid principals or groups in the current default realm of GlassFish Server. The role-name in this example must exactly match the role-name in the security-role element of the corresponding web.xml file or the role name defined in the @DeclareRoles and/or @RolesAllowed annotations.

Further Information about Advanced Security Topics

For more information about the security topics covered in this chapter, see