3.9 Declarative Security Policies
Security policies associated with URIs and enterprise beans include the following:
-
Login configurations associated with URIs: for example, use of form-based login
-
Authorization policies associated with URIs and enterprise beans based on J2EE security roles
-
Principal-delegation policies that apply to Web applications and enterprise beans
-
Connection policies associated with JCA connectors that dictate how applications access EIS in a secure manner
Such authorization and delegation policies can be specified declaratively within the relevant deployment descriptors.
3.9.1 Login-Configuration Policy
Authentication is the process of proving the identity of an entity. Authentication generally is performed in two steps: (1) acquiring the authentication data of a principal and (2) verifying the authentication data against a user (principal) registry.
J2EE security authenticates a principal on the basis of the authentication policy associated with the resource the principal has requested. When a user requests a protected resource from a Web application server, the server authenticates the user. J2EE servers use authentication mechanisms based on validating credentials, such as digital certificates (see Section 10.3.4 on page 372), and user ID and password pairs. Credentials are verified against a user registry that supports the requested authentication scheme. For example, authentication based on user ID and password can be performed against an LDAP user registry, where authentication is performed using an LDAP bind request.
A Web server is responsible for servicing HTTP requests. In a typical J2EE environment, a Web server is a component of a J2EE WAS. In this case, the WAS hosts servlets, JSP files, and enterprise beans. The loginauthenticationconfiguration is managed by the WAS, which drives the authentication challenges and performs the authentication. Similarly, if the Web server is independent of the WAS and the Web server is the front end for the WAS, the Web server acts as a proxy for J2EE requests. Again, the authentication is typically performed by the WAS.
The authentication policy for performing authentication among a user, a Web server, and a WAS can be specified in terms of the J2EE login configuration elements of a Web application's deployment descriptor. The authentication policy can specify the requirement for a secure channel and the authentication method.The requirement to use a secure channel when accessing a URI is specified through the user-data-constraint descriptor.
The authentication method is specified through the auth-method element in the login-config descriptor. There are three types of authentication methods:
-
HTTP authentication method. The credentials that the client must submit to authenticate are user ID and password, sent to the server as part of an HTTP header and typically retrieved through a browser's dialog window. The two modes of HTTP authentication are basic and digest. In both cases, the user ID is sent as cleartext.2 In basic authentication, the password is transmitted in cleartext as well; in digest authentication, only a hash value of the password is transmitted to the server (see Section 10.2.2.4 on page 356).
-
Form-based authentication method. The credentials that the client must submit to authenticate are user ID and password, which are retrieved through an HTML form.
-
Certificate-based authentication method. The credential that the client must submit is the client's digital certificate, transmitted over an HTTPS connection.
3.9.1.1 Authentication Method in Login Configuration
The auth-method element in the login-config element specifies how a server challenges and retrieves authentication data from a user. As noted previously, there are three possible authentication methods: HTTP (user ID and password), form based (user ID and password), and certificate based (X.509 certificate).
With the HTTP authentication method, the credentials provided by the user consist of a user ID and password pair, transmitted as part of an HTTP header. When HTTP authentication is specified, a user at a Web client machine is challenged for a user ID and password pair. The challenge usually occurs in the following way:
-
A WAS issues an HTTP unauthorized client error code (401) and a WWW_Authenticate HTTP header.
-
The Web browser pops up a dialog window.
-
The user enters a user ID and password pair in this dialog window.
-
The information is sent to the Web server.
-
The WAS extracts the information and authenticates the user, using the authentication mechanism with which it has been configured.
With HTTP authentication, a realm name also needs to be specified. Realms are used to determine the scope of security data and to provide a mechanism for protecting Web application resources. For example, a user defined as bob in one realm is treated as different from bob in a second realm, even if these two IDs represent the same human user, Bob Smith.
Once specified, the realm name is used in the HTTP 401 challenge to help the Web server inform the end user of the name of the application domain. For example, if the realm is SampleAppRealm, the dialog window prompting the user for a user ID and password pair during authentication will include that the user ID and password are to be supplied for the SampleAppRealm realm.
HTTP authentication can be either basic or digest. In basic authentication, the credentials requested of the user are user ID and password, and both are transmitted as cleartext. In order for the authentication method to be basic, the auth-method element in the login-config descriptor must be set to BASIC. Listing 3.4 is a deployment descriptor fragment showing an example of login configuration requiring basic authentication.
Listing 3.4. Login Configuration for Basic Authentication
<login-config> <auth-method>BASIC</auth-method> <realm-name>SampleAppRealm</realm-name> </login-config>
This scheme is not considered to be a secure method of user authentication, unless used in conjunction with some external secure systems, such as SSL.
In digest authentication, the user ID and a hash value of the password are transmitted to the server as part of an HTTP header. Therefore, the password does not appear in cleartext, which is the biggest weakness of basic authentication.
When digest authentication is specified, the Web server responds to the client's request by requiring digest authentication. A one-way hash of the password (see Section 10.2.2.4 on page 356), as specifed by the Request for Comments (RFC) 2617,3 is computed by the client, based on a random number, called nonce, uniquely generated by the server each time a 401 response is made. The hash value of the password is sent to the server, which computes the digest of the password for the user ID and compares the resulting hash value with the one submitted by the client. The requesting user is considered to be authenticated if the hash values are identical.
This mode of authentication assumes that the server has access to the user's password in cleartexta necessary requirement in order for the server to compute the hash of the password. However, this is rarely the case in most enterprise environments, as the password in cleartext is not retrievable from a user repository containing the user ID and password information. Rather, the server typically delegates responsibility to the user repository to validate a user's password. Therefore, digest authentication is not widely adopted in enterprise environments and hence is not required to be supported by a J2EE container.
J2EE servers that do support digest authentication can be configured to issue a digest authentication challenge by setting the value of the auth-method element in the login-config descriptor to DIGEST. Listing 3.5 is a deployment descriptor fragment illustrating how a J2EE server can be configured to require digest authentication.
Listing 3.5. Login Configuration for Digest Authentication
<login-config> <auth-method>DIGEST</auth-method> <realm-name>SampleAppRealm</realm-name> </login-config>
The second authentication method is form based. With this method, the auth-method element in the login-config element must be set to FORM. The form-based authentication method assumes that the server is configured to send the client an HTML form to retrieve the user ID and password from the Web user, as opposed to sending a 401 HTTP unauthorized client error code as in the basic challenge type.
The configuration information for a form-based authentication method is specified through the form-login-config element in the login-config element. This element contains two subelements: form-login-page and form-error-page.
-
The Web address to which a user requesting the resource is redirected is specified by the form-login-page subelement in the Web module's deployment descriptor. When the form-based authentication mode is specified, the user will be redirected to the specified form-login-page URL. An HTML form on this page will request a user ID and password.
-
If the authentication fails, the user is redirected to the page specified by the form-error-page subelement.
Listing 3.6 is a sample HTML page for the login form.
Listing 3.6. Login Page Contents
<HTML> <HEAD> <TITLE>Sample Login page.</TITLE> </HEAD> <BODY> <TR><TD> <HR><B>Please log in!</B><BR><BR> </TD></TR> <CENTER> Please enter the following information:<BR> <FORM METHOD=POST ACTION="j_security_check"> Account <INPUT TYPE=text NAME="j_username" SIZE=20><BR> Password <INPUT TYPE=password NAME="j_password" SIZE=20><BR> <INPUT TYPE=submit NAME=action VALUE="Submit Login"> </FORM><HR> </CENTER> </BODY> </HTML>
Listing 3.7 is a deployment descriptor fragment showing an example of login configuration that requires form-based authentication.
Listing 3.7. Login Configuration for Form-Based Authentication
<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.html</form-login-page> <form-error-page> /login-failed.html </form-error-page> </form-login-config> </login-config>
The third type of authentication method is certificate based (X.509 certificate). In order for the authentication method to be certificate based, the auth-method element in the login-config descriptor must be set to CLIENT-CERT. The certificate-based authentication method implies that the Web server is configured to perform mutual authentication over SSL. The client is required to present a certificate to establish the connection. When the CLIENT-CERT mode is specified, the client will be required to submit the request over an HTTPS connection. If the request is not already over HTTPS, the J2EE product will redirect the client over an HTTPS connection. Successful establishment of an SSL connection implies that the client has presented its own certificate and not anyone else's. The details of how the server ensures that the client certificate really belongs to the client are explained in Section 10.3.4 on page 372 and Section 13.1.2 on page 452. The certificate used by the client is then mapped to an identity in the user registry the J2EE product is configured to use.
Listing 3.8 is a deployment descriptor fragment showing an example of login configuration that requires certificate-based authentication.
Listing 3.8. Login Configuration for Certificate-Based Authentication
<login-config> <auth-method>CLIENT-CERT</auth-method> </login-config>
Note that the user registry is not specified in this XML deployment descriptor fragment because it is not part of the J2EE specification.
3.9.1.2 Secure-Channel Constraint
Establishing an HTTPS session between the client and the Web server is often a necessary requirement to provide data confidentiality and integrity for the information flowing between the HTTP client and the server. In a J2EE environment, the security policy can require the use of a secure channel, specified through the user-data-contraint deployment descriptor element. When the requirement for a secure channel is specified, the request to the URI resource should be initiated over an HTTPS connection. If access is not already via a HTTPS session, the request is redirected over an HTTPS connection.
Specifying INTEGRAL or CONFIDENTIAL as the value for the transport-guarantee element in the user-data-constraint descriptor will be treated as a requirement for the HTTP request to be over SSL. This requirement can be specified as part of the user-data-constraint element in a Web application's login configuration. In theory, INTEGRAL should enforce communitcation integrity, whereas CONFIDENTIAL should enforce communication confidentiality, and it could be possible to select different cipher suites to satisfy these requirements. However, a J2EE server typically does not differentiate INTEGRAL from CONFIDENTIAL but instead treats both of these values to indicate the need to require an SSL connection with a particular cipher suite, not based on whether INTEGRAL or CONFIDENTIAL was specified.
Listing 3.9 is a deployment descriptor fragment showing an example of login configuration that contains the user-data-constraint element. More details are provided in Section 4.6.6 on page 132.
Listing 3.9. Specifying the Requirement for a Secure Channel
<user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint>
3.9.2 Authorization Policy
The role-permission interpretation of the J2EE security model treats a security role to be a set of permissions. The security role uses the role-name label defined in the method-permission element of an EJB module's deployment descriptor and in the security-constraint element of a Web module's deployment descriptor as the name of the set of permissions. The set of permissions defines a number of resourcesthe enterprise beans and the Web resources to which the method-permission and security-constraint elements refer, respectivelyand a set of actionsthe methods listed by the method-permission and the security-constraint descriptors. For example, in Listing 3.2 on page 74, the security role Teller is associated with the permissions to invoke the getBalance() and getDetails() methods on the AccountBean enterprise bean. Similarly, in Listing 3.3 on page 75, the security role Teller is associated with the permission to perform a GET invocation over HTTP to the /finance/account/ URI. If multiple method-permission and security-constraint descriptors refer to the same security role, they are all taken to contribute to the same role permission. In other words, the sets of permissions associated with that security role are merged to form a single set.
This model has the advantage of dramatically reducing the number of objects in a security object spacea set of pairs (subject, <target, operation>), where the subject is an entity requesting to perform a security-sensitive operation on a given target. The Deployer and the System Administrator can define authorization policies, associated with EJB or URI targets and the operations of enterprise bean methods and HTTP methods, respectively, for the security roles in their applications. Then, they associate subjects to security roles; by extension, those subjects are granted the permissions to perform the operations permitted by the security roles.
Based on the J2EE security model, a protected action can be performed by a subject who has been granted at least one of the security roles associated with the action. The security roles associated with a protected action are the required security rolesthe permissions necessary to perform the action itself. The roles associated with a subject are the granted security rolesthe permissions that have been given to that subject. This means that the subject will be allowed to perform an action if the subject's granted security roles contain at least one of the required security roles to perform that action. For example, if the action consisting of accessing the EJB method getDetails() on the AccountBean enterprise bean can be performed only by the security roles Teller and Supervisor and if subject Bob has been granted the security role of Teller, Bob will be allowed to perform that action, even if Bob has not been granted the security role of Supervisor.
The table that represents the association of security roles to sets of permissions is called the method-permission table. A method-permission table (see Table 3.1) can be used to deduce the set of required security roles. The rows in the table represent security roles; the columns represent protected actions.
It can be inferred from Table 3.1 that in order to access the getBalance() method on AccountBean, the required security roles are Teller and Supervisor. In order to access any URI that matches the pattern /public/*, a PublicRole is required.
Table 3.1. Example of Method-Permission Table
/finance/accountGET |
/finance/accountPUT |
/public/* |
AccountBean.getBalance() |
AccountBean.getDetails() |
|
---|---|---|---|---|---|
Teller |
Yes |
No |
No |
Yes |
Yes |
Supervisor |
Yes |
Yes |
No |
Yes |
Yes |
PublicRole |
No |
No |
Yes |
No |
No |
The table that represents the association of roles to subjects is called the authorization table, or protection matrix. In such a table, the security role is defined as the security object, and users and groups are defined as security subjects. An authorization table (see Table 3.2) can be used to deduce the set of granted security roles. The rows in the table refer to the users and user groups that are security subjects in the protection matrix; the columns represent the J2EE security roles that are security objects in the protection matrix.
The method-permission table and the protection matrix reflect the configuration specified in the deployment descriptors. For example, the first row in Table 3.1 reflects the deployment descriptor obtained from the deployment descriptor fragments of Listing 3.2 on page 74 and Listing 3.3 on page 75. It can be inferred from Table 3.2 that user Bob and group TellerGroup are granted the security role of Teller, everyone is granted the PublicRole, and only users in the ManagerGroup are granted the security role of Supervisor.
Combining Table 3.1 and Table 3.2, it follows that Bob can access the getBalance() and getDetails() methods on the AccountBean enterprise bean and can issue an HTTP GET request on the /finance/account/ URI. Bob cannot, however, issue an HTTP PUT request on the /finance/account/ URI. Note that Bob will be able to access any URI that matches /public/*, as everyone has been granted the role PublicRole, which is the role necessary to get access to /public/*.
In the J2EE security model, the Application Assembler defines the initial mapping of actions on the protected resources to the set of the required security roles (see Section 3.7.2 on page 67). This can be done using the application assembly tool. Subsequently, the Deployer will refine the policies specified by the Application Assembler when installing the application into a J2EE environment (see Section 3.7.3 on page 70). The Deployer also can use the application assembly tool to redefine the security policies, when necessary, and then install the application into the J2EE container. The method-permission table is formed as a result of the required security roles getting specified through the process of application assembly and refinement during deployment.
Table 3.2. Example of Authorization Table
Teller |
Supervisor |
PublicRole |
|
---|---|---|---|
TellerGroup |
Yes |
No |
No |
ManagerGroup |
No |
Yes |
No |
Everyone |
No |
No |
Yes |
Bob |
Yes |
No |
No |
Authorization policies can be broadly categorized into application policies, which are specified in deployment descriptors and map J2EE resources to roles, and authorization bindings, which reflect role to user or group mapping. As discussed in Section 3.7.2 on page 67, a set of security roles is associated with actions on J2EE protected resources. These associations are defined in the J2EE deployment descriptors when an application is assembled and deployed. The security roles specified in this way are the required security rolesthe sets of permissions that users must be granted in order to be able to perform actions on protected resources. Pragmatically, before a user is allowed to perform an action on a protected resource, either that same user or one of the groups that user is a member of should be granted at least one of the required security roles associated with that protected resource. The authorization table that relates the application-scoped required security roles to users and user groups is managed within the J2EE Product Provider using the J2EE Product Provider configuration tools.
3.9.3 Delegation Policy
Earlier in this chapter, we defined delegation as the process of forwarding a principal's credentials with the cascaded downstream requests. Enforcement of delegation policies affects the identity under which the intermediary will perform the downstream invocations on other components. By default, the intermediary will impersonate the requesting client when making the downstream calls. The downstream resources do not know about the real identity, prior to impersonation, of the intermediary. Alternatively, the intermediary may perform the downstream invocations using a different identity. In either case, the access decisions on the downstream objects are based on the identity at the outbound call from the intermediary. To summarize, in a J2EE environment, the identity under which the intermediary will perform a task can be either
-
The client's identity the identity under which the client is making the request to the intermediary
-
A specified identity an identity in terms of a role indicated via deployment descriptor configuration
The application deployment environment determines whether the client or a specified identity is appropriate.
The Application Assembler can use the security-identity element to define a delegation identity for an enterprise bean's method in the deployment descriptor. Consider an example in which a user, Bob, invokes methods on a SavingsAccountBean enterprise bean. SavingsAccountBean exposes three methodsgetBalance(), setBalance(), and transferToOtherBank()and its delegation policy is defined as in Table 3.3. Figure 3.5 shows a possible scenario based on the delegation policy specified in Table 3.3.
Figure 3.5. Delegation Policy Scenario
The method setBalance() will execute under the client's identity because the delegation mode is set to use-caller-identity. The method getBalance() will execute under the client's identity as well because no delegation mode is specified, and the default is use-caller-identity. Therefore, if Bob invokes the method getBalance() on AccountBean, the method will execute under Bob's identity, bob. Suppose that the getBalance() method invokes a lookup() method on SavingsAccountBean. This invocation will still be executed under Bob's identity and will succeed only if Bob has been granted the permission to invoke lookup() on SavingsAccountBean.
Table 3.3. SavingsAccountBean Enterprise Bean's Delegation Policy
Method |
Delegation Mode |
Specified Role |
---|---|---|
getBalance() |
||
setBalance() |
use-caller-identity |
|
transferToOtherBank() |
run-as |
Supervisor |
Any downstream call from transferToOtherBank() will perform method calls on a TransferBean enterprise bean. These invocations will need to execute under a principal that has been granted the Supervisor role. The Deployer or the System Adminstrator needs to map the Supervisor role to a principal that has been granted the Supervisor role. This can be done by specifying a valid user ID and password pair corresponding to a user who has been granted that role. For example, if user Alice has been granted the Supervisor role and if the user ID and password pair for Alice is associated with the Supervisor role, the calls to transferToOtherBank() will occur under Alice's identity.
3.9.4 Connection Policy
Information in any EIS must be protected from unauthorized access. An EIS system is likely to have its own authorization model. At a minimum, most of these systems have facilities to accept some form of authentication data representing an identity connecting to the EIS. The JCA is designed to extend the end-to-end security model for J2EE-based applications to include integration with EISs. A WAS and an EIS collaborate to ensure the proper authentication of a resource principal when establishing a connection to a target EIS. As discussed in Section 3.4 on page 61, the JCA allows for two ways to sign on to an EIS: container-managed sign-on and component-managed sign-on.
With container-managed sign-on, the connection to an EIS is obtained through declarative security. In order for a connection to be container managed, the deployment descriptor will indicate that the res-auth element associated with a resource definition is declared as Container. If the connection is obtained by passing the identity information programmatically, the value for res-auth should be set to Application. Details of component-managed sign-on are discussed in Section 3.10.3 on page 96.
A deployment descriptor fragment that declares that the authentication facilitated by the resource adapter should be set to be Container is shown in Listing 3.10.
Listing 3.10. An XML res-auth Element in a Deployment Descriptor
<resource-ref> <description>Connection to myConnection</description> <res-ref-name>eis/myConnection</res-ref-name> <res-type>javax.resource.cci.ConnectionFactory</res-type> <res-auth>Container</res-auth> </resource-ref>
The container is responsible for obtaining appropriate user authentication information needed to access the EIS. The connection to the EIS is facilitated by the specified resource adapter. The JCA allows specifying the authentication mechanism. The authentication-mechanism-type element in the deployment descriptor is used to specify whether a resource adapter supports a specific authentication mechanism. This XML element is a subelement of the authentication-mechanism element. The JCA specification supports the following authentication mechanisms:
-
Basic authentication. The authentication mechanism is based on user ID and password. In this case, the authentication-mechanism-type XML element in the deployment descriptor is set to BasicPassword.
-
Kerberos V5. The authentication mechanism is based on Kerberos V5. In this case, the authentication-mechanism-type element in the deployment descriptor is set to Kerbv5.
Other authentication mechanisms are outside the scope of the JCA specification.
In a secure environment, it is likely that a J2EE application component, such as an enterprise bean, and the EIS system that is accessed through the component are secured under different security domains, where a security domain is a scope within which certain common security mechanisms and policies are established. In such cases, the identity under which the J2EE component is accessed should be mapped to an identity under which the EIS is to be accessed. Figure 3.6 depicts a possible scenario.
Figure 3.6. Credential Mapping when Accessing an EIS from a J2EE Container
In this scenario, an enterprise bean in a J2EE container is accessed by a user, Bob Smith. The enterprise bean is protected in a way that it allows only users from a specified LDAP directory to access it. Therefore, the identity under which Bob Smith will access the enterprise bean must be registered in that LDAP directory. Bob Smith uses the identity of bsmith when he accesses the enterprise bean.
In a simplistic case, where the run-as policy of the enterprise bean is set to be the caller identity, the connections to the EIS will be obtained on behalf of Bob Smith. If the connections are obtained through user ID and password, when the enterprise bean obtains a connection to a back-end system, such as a CICS system, the J2EE container will retrieve a user ID and password to act on behalf of user bsmith. The application invokes the getConnection() method on the javax.resource.cci.ConnectionFactory instance (see Listing 3.10 on page 89) with no security-related parameters, as shown in Listing 3.11, a fragment of Java code.
The application relies on the container to manage the sign-on to the EIS instance. This is possible in simple deployment scenarios in which the identity under which the EIS system is accessed is specified by the Deployer. This effectively means that all identities accessing the application are mapped to a single identity to access the EIS system: a many-to-one identity mapping.
Listing 3.11. Getting a Connection to an EIS with Container-Managed Sign-On
// Construct the InitialContext Context initctx = new InitialContext(); // Perform a JNDI lookup to obtain a ConnectionFactory javax.resource.cci.ConnectionFactory cxf = (javax.resource.cci.ConnectionFactory) initctx.lookup ("java:comp/env/eis/MyEIS"); // Invoke the ConnectionFactory to obtain a connection. // The security information is not passed to the // getConnection() method javax.resource.cci.Connection cx = cxf.getConnection();
In more sophisticated deployment scenarios, a many-to-one identity mapping may not be sufficient for security policy reasons. For example, it may be necessary for the EIS system to log all the identities that accessed it. For this logging facility to be useful, the identities accessing a J2EE application must not all be mapped to the same identity on the EIS system. A one-to-one or many-to-many identity mapping is recommended in this case. In particular, the container may use a credential mapping facility whereby bsmith is mapped to user ID bobsmith and password db2foobar, as shown in Figure 3.6.
If connections require Kerberos credentials or other generic credentials to be passed, the mapping facility is responsible for mapping one form of the credential to another that can be used by the target security domain. The manner in which these mappings happen and the level of sophistication in mapping available in J2EE application servers are server specific and not dictated by the J2EE specification.
In enterprise environments consisting of multiple departments, organizations, and even acquired companies, it is typical for systems to be interconnected and the applications shared. In such environments in which J2EE applications are deployed, it is a good architectural approach to design the application integration in a way that applications use JCA to obtain connections to other applications and to follow the declarative approach to define connection sign-on, as explained in this section. The use of JCA will make applications unaware of cross-security domains when accessing non-J2EE systems, and the use of declarative security will enhance application flexibility and portability. JCA with declarative security will also help manage the mapping of credentials and identities outside the application as enforced and facilitated by the enterprise-level mapping infrastructure.