Configuring EJB application security using WebSphere Application Server Community Edition

The security configuration in WebSphere® Application Server Community Edition 2.x differs from the previous versions due to the introduction of credential store, run-as-subject and default-subject. This article shows how to configure EJB Application security using WebSphere Application Server Community Edition V2. It familiarizes you with various security related annotations, elements in EJB deployment descriptors, and Community Edition specific deployment plans to secure session, entity and message-driven EJBs.

Vamsavardhana Reddy Chillakuru (vamsic007@in.ibm.com), Advisory Software Engineer, EMC

Author photoVamsavardhana Reddy Chillakuru (a.k.a Vamsi) is an Advisory Software Engineer at IBM India Software Labs in Bangalore, India. He is a committer on Apache Geronimo and Apache Tuscany projects, a member of the Apache Geronimo Project Management Committee, and is part of the IBM WebSphere Application Server Community Edition Level 3 Support Team. He received his Bachelor of Statistics (Hons.) and Master of Statistics degrees from the Indian Statistical Institute, Kolkata, India in the years 1994 and 1996, respectively.



Manu T. George (mageorge@in.ibm.com), Staff Software Engineer, IBM

author photoManu T. George is a Staff Software Engineer at IBM India Software Labs in Bangalore, India. He is a committer on Apache Geronimo and Apache OpenEJB projects, and is a part of the IBM WebSphere Application Server Community Edition Level 3 Support Team. He received his Bachelor of Technology in Applied Electronics from the College of Engineering Trivandrum in the year 2001.



26 November 2008

Also available in Chinese Japanese

Introduction

Securing Enterprise Java Beans (EJBs) is one of the most important aspects of Java EE application security. IBM WebSphere Application Server Community Edition V2.1 (hereafter referred to as Community Edition) is a free-to-use Java Enterprise Edition 5.0 (Java EE5) certified application server based on Apache Geronimo v2.1 that provides for securing EJB applications. Community Edition uses Apache OpenEJB as its EJB container. You configure EJB authentication and authorization by defining security roles in the deployment descriptor under which each method executes. You then map the security roles to principals in the Community Edition specific deployment plan.

In this article we discuss the different options available to secure session, entity and message-driven EJBs using Community Edition. We also develop a few EJB applications to demonstrate the various security configurations. To follow along you need WebSphere Application Server Community Edition v2.1.


A simple EJB application without security

Let's examine a simple EJB application that has no security configured. This application contains an EJB2.1 stateless session bean and an EJB3 stateless session bean. Listing 1 shows this application's deployment descriptor ejb-jar.xml.

Listing 1: Deployment descriptor showing bean definition
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar ...>
    <display-name>SimpleEjbApp</display-name>
    <enterprise-beans>
        <session>
            <description>Simple Session Bean</description>
            <display-name>SimpleSessionBean</display-name>
            <ejb-name>SimpleSessionBean</ejb-name>
            <home>simple.ejb21.SimpleServiceHome</home>
            <remote>simple.ejb21.SimpleService</remote>
            <local-home>simple.ejb21.SimpleServiceLocalHome</local-home>
            <local>simple.ejb21.SimpleServiceLocal</local>
            <ejb-class>simple.ejb21.SimpleServiceBean</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
        </session>
    </enterprise-beans>
</ejb-jar>

Notice that the deployment descriptor shows only one bean definition, namely SimpleSessionBean. We specify the deployment metadata of the EJB3 session bean using annotations in the bean class. Listing 2 shows the bean class of Simple3ServiceBean.

Listing 2: Simple3ServiceBean class
import  javax.ejb.Stateless;
...

@Stateless
public class Simple3ServiceBean implements Simple3Service {

	  public String commonMethod(){
		  ...
	  }

	  public String userMethod(){
		  ...
	  }

	  public String adminMethod(){
		  ...
	  }
	  
	  public String noaccessMethod(){
		  ...
	  }
}

In this example the @Stateless annotation specifies that Simple3ServiceBean is a stateless session bean.

Both the session beans SimpleSessionBean and Simple3ServiceBean do not have any security configured and so all the methods have unrestricted access. The deployment plan openejb-jar.xml for this application is show in Listing 3.

Listing 3: Simple EJB application deployment plan
<openejb-jar ...>
    <environment>
        <moduleId>
            <groupId>dw</groupId>
            <artifactId>simple-ejb-app</artifactId>
            <version>1.0</version>
            <type>jar</type>
        </moduleId>
        <dependencies/>
        <hidden-classes/>
        <non-overridable-classes/>
    </environment>
    <enterprise-beans>
        <session>
            <ejb-name>SimpleSessionBean</ejb-name>
            <jndi-name>ejb/SimpleSessionBean</jndi-name>
        </session>
    </enterprise-beans>
</openejb-jar>

The EJB application is deployed under a module with ID dw/simple-ejb-app/1.0/jar. Note that we'll use the information under moduleId element to map to the EJBs in this application as we will see later in this article.


A simple web application to demonstrate EJB security

In this article, we use a simple Web application to demonstrate EJB security. The Web application uses two security roles namely “bank” and “customer”. The Web application consists of a home page with unrestricted access and two secure pages accessible by “bank” and “customer” roles. Each of the pages access SimpleSessionBean and Simple3ServiceBean methods and display the result from the method or any exceptions thrown at method invocation. Listing 4 shows the web.xml deployment descriptor.

Listing 4: Simple web application deployment-descriptor
<web-app ...>
    <display-name>simple-web-app</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        ...
    </welcome-file-list>

    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>Not required for FORM auth</realm-name>
        <form-login-config>
            <form-login-page>/login/login.jsp</form-login-page>
            <form-error-page>/login/loginerror.jsp</form-error-page>
        </form-login-config>
    </login-config>

    <security-role>
        <role-name>customer</role-name>
    </security-role>
    <security-role>
        <role-name>bank</role-name>
    </security-role>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Customer</web-resource-name>
            <url-pattern>/customer/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>customer</role-name>
                 <!-- This comes from the security-role element -->
        </auth-constraint>
    </security-constraint>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Bank</web-resource-name>
            <url-pattern>/bank/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>bank</role-name> 
                   <!-- This comes from the security-role element -->
        </auth-constraint>
    </security-constraint>

    <ejb-ref>
        <ejb-ref-name>ejb/SimpleService</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <home>simple.ejb21.SimpleServiceHome</home>
        <remote>simple.ejb21.SimpleService</remote>
    </ejb-ref>
    <ejb-ref>
        <ejb-ref-name>ejb/Simple3Service</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <remote>simple.ejb3.Simple3Service</remote>
    </ejb-ref>
    ....
</web-app>

The Web application uses FORM authentication as configured in the login-config element. The two security roles are defined using security-role elements. We use the security-constraint tag to configure security permissions for resource collections. In this sample, users in the bank role can access URLs with the pattern /bank/* and users in the customer role can access URLs with pattern /customer/*.

We use the ejb-ref element to declare EJB references for accessing the bean through its remote home and remote interfaces. In this sample, we define two EJB references namely ejb/SimpleService and ejb/Simple3Service. Notice that there is no home interface defined for the Simple3Service bean, which is an EJB3 session bean. You can use the ejb-local-refelement to declare EJB references used for accessing the bean through its local home and local interfaces.

In the geronimo-web.xml Web application deployment plan, we map the EJB references defined in web.xml to specific EJBs, and map the security roles to principals. Listing 5 shows the deployment plan for the sample Web application.

Listing 5: Simple web application deployment plan
<web-app ...>
    ...
    <context-root>simple-web-app</context-root>
    <nam:ejb-ref xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.2">
        <nam:ref-name>ejb/SimpleService</nam:ref-name>
        <nam:pattern>
            <nam:groupId>dw</nam:groupId>
            <nam:artifactId>simple-ejb-app</nam:artifactId>
            <nam:version>1.0</nam:version>
            <nam:name>SimpleSessionBean</nam:name>
        </nam:pattern>
    </nam:ejb-ref>
    <nam:ejb-ref xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.2">
        <nam:ref-name>ejb/Simple3Service</nam:ref-name>
        <nam:pattern>
            <nam:groupId>dw</nam:groupId>
            <nam:artifactId>simple-ejb-app</nam:artifactId>
            <nam:version>1.0</nam:version>
            <nam:name>Simple3ServiceBean</nam:name>
        </nam:pattern>
    </nam:ejb-ref>
    ...
    <security-realm-name>SampleSecurityRealm</security-realm-name>
    <app:security ...>
        ...
        <sec:role-mappings>
            <sec:role role-name="customer">
                <sec:principal name="UserGrp" 
                    class="o.a.g.s.r.providers.GeronimoGroupPrincipal"/>
                ...
            </sec:role>
            <sec:role role-name="bank">
                <sec:principal name="AdminGrp" 
                    class="o.a.g.s.r.providers.GeronimoGroupPrincipal"/>
            ...
            </sec:role>
        </sec:role-mappings>
    </app:security>
</web-app>

We use the ejb-refelement to map an EJB reference to specific EJBs. In this example, notice that the value in the ref-name element under ejb-refmatches the value in ejb-ref-name element under ejb-ref in web.xml (see Listing 4). Similarly, we use the ejb-local-ref element to map EJB local references to specific EJBs.

The security-realm-name element is used to configure the security realm against which the application authenticates the users. In this example, we use a realm with name SampleSecurityRealm.

The security roles are mapped to principals under the role-mappings element inside the security element. We use a role element for each security role to be mapped. The name of the security role is specified in the role-name attribute of the role element. We specifiy the principals that map to the security role using principal elements inside the role element. In this example, we map the bank role to a GeronimoGroupPrincipal with name AdminGrp and the customerrole to a GeronimoGroupPrincipal with name UserGrp. See Configuring Web application security in WebSphere Application Server Community Edition V2.0 provided in the Resources for a detailed explanation of principal to role mapping.


Run the sample application without EJB security

We will now run the simple Web application that accesses the EJBs in the EJB application. Note that at the moment we have no security configured for the EJBs. Before proceeding further, download and extract the samples archive to a directory of your choice, (we will refer to this directory as <SAMPLES_HOME>) and copy dw_users.properties and dw_groups.properties files to <WASCE_HOME>/var/security directory (<WASCE_HOME> refers to the Community Edition installation directory).

To run the sample application:

  1. Start Community Edition and open http://localhost:8080/console/ in your browser.
  2. Enter system for the user name and manager for the password. Click Login, which brings up the Welcome page in the administrative console.
  3. Navigate to the Deploy New portlet.
  4. Under the Plan field, navigate to <SAMPLES_HOME> and select the file SampleSecurityRealm-plan.xml.
  5. Click Install to complete the security realm deployment.
  6. Under the Archive field, navigate to <SAMPLES_HOME> and select simple-ejb-app.jar.
  7. Click Install to complete EJB application deployment.
  8. Under the Archive field, navigate to <SAMPLES_HOME> and select simple-web-app.war.
  9. Click Install to complete Web application deployment.
  10. Access http://localhost:8080/simple-web-app , which shows the screen in Figure 1.
    Figure 1: Web application home page
    Screen shot of Web application home page

    The User Info section shows the currently logged in user's UserPrincipal and UserRoles in the web application. The EJB2.1 section shows the result of invoking each of the methods in SimpleSessionBean. The EJB3 section shows the result of invoking each of the methods in Simple3ServiceBean. Since we have not logged into the application, the UserPrincipal and UserRole is empty. Since no security is configured for any of the EJB methods, all the methods are accessible and are invoked as an Unauthenticated user.

  11. Access http://localhost:8080/simple-web-app/bank . Login as user dwadmin using password admin,which shows the screen in Figure 2.
    Figure 2: Web application bank page
    Screen shot of Web application bank page

    Notice that the UserPrincipal shows the logged in user dwadmin and the UserRole as bank. Since no security is configured for any of the EJB methods, all the methods are accessible and are invoked as an Unauthenticated user.

So far we have seen the Web application invoking EJB2.1 and EJB3 session beans with unrestricted method access. Next we'll configure method permissions for EJB2.1 and EJB3 session beans.


Security configuration in EJB2.1 deployment descriptors

EJB applications use role-based security for bean-level and method-level security. In this section we see how to define security roles and configure method permissions.

Defining Security Roles

We define security roles in the deployment descriptor file ejb-jar.xml using a security-role element under assembly-descriptor. The role-name element specifies the name of the security role. Listing 6 shows an excerpt of ejb-jar.xml from one of the sample applications used in this article.

Listing 6: Assembly-descriptor showing role definitions
<ejb-jar ...>
    <display-name>SimpleEjbApp</display-name>
    <enterprise-beans>
    ...
    </enterprise-beans>
    <assembly-descriptor>
      <security-role>
         <description>User role</description>
         <role-name>ejbuser</role-name>
      </security-role>
      <security-role>
         <description>Administrator role</description>
         <role-name>ejbadmin</role-name>
      </security-role>
      ...
    </assembly-descriptor>
</ejb-jar>

In this example the application defines two roles, namely ejbuser and ejbadmin.

Configuring method permissions

To configure the security identity to invoke the methods in an EJB, we use the security-identity element in the bean definitions under enterprise-beans element in ejb-jar.xml. We configure the bean method permissions by using the method-permission element under assembly-descriptor in ejb-jar.xml. Listing 7 shows fragments of the EJB application deployment descriptor used to configure the method permissions for SimpleSessionBean.

Listing 7: EJB application deployment descriptor
<ejb-jar id="SimpleEjbAppWithSecurity" ...>
    <enterprise-beans>
        <session>
            ...
            <ejb-name>SimpleSessionBean</ejb-name>
            ...
            <security-identity>
                <use-caller-identity />
            </security-identity>
        </session>
        ...
    </enterprise-beans>
    <assembly-descriptor>
        <security-role>
        ...
        </security-role>
        <method-permission>
            <role-name>ejbuser</role-name>
            <method>
                <ejb-name>SimpleSessionBean</ejb-name>
                <method-name>userMethod</method-name>
            </method>
        </method-permission>
        <method-permission>
            <role-name>ejbadmin</role-name>
            <method>
                <ejb-name>SimpleSessionBean</ejb-name>
                <method-name>adminMethod</method-name>
            </method>
        </method-permission>
        <method-permission>
            <unchecked/>
            <method>
                <ejb-name>SimpleSessionBean</ejb-name>
                <method-name>commonMethod</method-name>
            </method>
        </method-permission>
        <method-permission>
            <role-name/>
            <method>
                <ejb-name>SimpleSessionBean</ejb-name>
                <method-name>noaccessMethod</method-name>
            </method>
        </method-permission>
    </assembly-descriptor>
</ejb-jar>

Let's walk through the tags we used in this example:

  • The security-identity element specifies the security identity to be used to invoke methods in SimpleSessionBean.
  • The use-caller-identity element specifies that the caller's security identity be used as the security identity for the execution of the enterprise bean's methods. Another option is to use a run-aselement to specify that a run-as identity be used to invoke the bean's methods as we show later in this article.
  • The method-permission'smethod element specifies the security permissions for one or more methods in a bean.
  • You can specify permissions using one or more role-name elements, one for each role that is allowed to access the method. A single, empty role-name element means the role has no access to the method. You specify unrestricted access permission using an unchecked element.
  • The method's ejb-name element specifies the name of the EJB. The method-name element specifies the name of the method. A value of “*” for method-name corresponds to all methods in the EJB.
  • A specific method-name corresponds all methods of that name, including any overloaded methods. To specify a particular method from overloaded methods, use the method-params element.
  • You can configure method-permission for methods in the bean's Home, Remote, Local and LocalHome interfaces. To specify the permission for a method in a particular interface, use the method-intf element under method with the corresponding value.

In Listing 7, in the SimpleSession bean, we have configured:

  • userMethod to be accessible by ejbuser role.
  • adminMethod to be accessible by ejbadmin role.
  • commonMethod to have unrestricted access.
  • noaccessMethod to be inaccessible by any role.

Security configuration in EJB3 beans using annotations

In EJB3 enterprise beans, you can configure the bean-level and method-level security using security annotations. In this section, we discuss the various security annotations (@DeclareRoles, @DenyAll, @PermitAll, @RolesAllowed) and how they affect the security configuration. Note that we'll discuss the @RunAs annotation later in the article.

Defining security roles

You define security roles by using a @DeclareRoles annotation on a bean class, as shown in Listing 8.

Listing 8: Simple3ServiceBean with @DeclareRoles annotation
@Stateless
@DeclareRoles({"ejb3user", "ejb3admin"})
public class Simple3ServiceBean implements Simple3Service {
...
}

In this example, Simple3ServiceBean defines two security roles, namely ejb3user and ejb3admin.

Configuring method permissions

You configure permissions for enterprise beans methods using the @DenyAll, @PermitAll and @RolesAllowed annotations. The @PermitAll and @RolesAllowed annotations can be applied on the bean class as well as bean methods, whereas @DenyAll annotation can be applied only on bean methods. An annotation applied on a class is applicable to all the methods in the class. An annotation applied on a method overrides any annotation applied on the class. Listing 9 shows Simple3ServiceBean class.

Listing 9: Simple3ServiceBean class with security annotations
@Stateless
@DeclareRoles({"ejb3user", "ejb3admin"})
public class Simple3ServiceBean implements Simple3Service {

	  @Resource
	  private SessionContext ctx;
	
        @PermitAll
	  public String commonMethod() {
		  return logCall("commonMethod");
	  }

        @RolesAllowed({"ejb3user"})
	  public String userMethod() {
		  return logCall("userMethod");
	  }

        @RolesAllowed({"ejb3admin"})
	  public String adminMethod() {
		  return logCall("adminMethod");
	  }
	  
        @DenyAll
	  public String noaccessMethod() {
		  return logCall("noaccessMethod");
	  }
	  
	  private String logCall(String method) {
              ...
		  return msg;
	  }
}

This example defines the following access configuration:

  • commonMethod has unrestricted access.
  • userMethod is accessible by ejb3user role.
  • adminMethod is accessible by ejb3admin role.
  • noaccessMethod is not accessible by any role.

Security role mapping in the EJB deployment plan

The security roles defined in the EJB deployment descriptor and the roles defined using the @DeclareRoles annotation are mapped to principals in the EJB deployment plan openejb-jar.xml. shows the principal to role mapping in the EJB deployment plan.

Listing 10: principal to role mapping
<security>
    <role-mappings>
        <role role-name="ejbuser">
            <principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal" 
                  name="UserGrp"/>
        </role>
        <role role-name="ejbadmin">
            <principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal" 
                  name="AdminGrp"/>
        </role>
        <role role-name="ejb3user">
            <principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal"
                  name="UserGrp"/>
        </role>
        <role role-name="ejb3admin">
            <principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal" 
                  name="AdminGrp"/>
            <principal class="o.a.g.s.r.providers.GeronimoUserPrincipal" 
                  name="dwuser3"/>
        </role>
    </role-mappings>
</security>

Notice that the security roles in ejb-jar.xml and in the @DeclareRoles annotation are mapped to principals:

  • The ejbuser role is mapped to a GeronimoGroupPrincipal with name “UserGrp”.
  • The ejbadmin role us mapped to a GeronimoGroupPrincipal with name “AdminGrp”.
  • The ejb3user role is mapped to a GeronimoGroupPrincipal with name “UserGrp”.
  • The ejb3admin role is mapped to a GeronimoGroupPrincipal with name “AdminGrp” and a GeronimoUserPrincipal with name “dwuser3”.

See Configuring Web application security in WebSphere Application Server Community Edition V2.0 for a detailed explanation of the principal to role mapping.


Run the sample application with EJB security

Navigate to the Deploy New portlet.

  1. Under the Archive files, navigate to <SAMPLES_HOME> and select simple-ejb-app-w-security.jar.
  2. Select the Redeploy application option and click Install.
  3. Navigate to the Web App WARs portlet and start dw/simple-web-app/1.0/war.
  4. Access http://localhost:8080/simple-web-app , which shows the screen in Figure 3.
    Figure 3: Web application home page accessing secure EJBs
    Screen shot of home page accessing secure EJBs

    Note that since the user has not logged into the application, only commonMethod in SimpleSessionBean and Simple3ServiceBean (which has unrestricted access) is invokable from the home page. All the other method invocations resulted in AccessException or EJBAccessException since the Principal is not authorized.

  5. Access http://localhost:8080/simple-web-app/bank/. Log in with name dwadmin using password admin,which shows the screen in Figure 4.
    Figure 4: Web application bank page accessing secure EJBs
    Screen shot of bank page accessing secure EJBs

    Since the user is now logged in as dwadmin, the Subject contains GeronimoUserPrincipal with name dwadmin and GeronimoGroupPrincipal with name AdminGrp. The user maps to ejbadmin and ejb3admin roles as per the role mapping. So the user can access commonMethod, which has unrestricted access, and adminMethod, which is accessible (by the ejbadmin role for SimpleSessionBean and the ejb3admin role for Simple3ServiceBean). The userMethod and noaccessMethod resulted in AccessException or EJBAccessException upon invocation. userMethod is accessible by the ejbuser role (ejb3user role for Simple3ServiceBean), and noaccessMethod is not accessible by any role,

  6. Open a new browser window and access http://localhost:8080/simple-web-app/customer/ . Login with name dwuser3 using password user3, which shows the screen in Figure 5.
    Figure 5: Web application customer page accessing secure EJBs
    Screen shot of customer page accessing secure EJBs

    Since the user is now logged in as dwuser3, the Subject contains GeronimoUserPrincipal with name dwuser3and GeronimoGroupPrincipal with name UserGrp. The user maps to ejbuser, ejb3user and ejb3admin roles as per the role mapping. In SimpleSessionBean, the user can access commonMethod, which has unrestricted access and the userMethod that is accessible by the ejbuser role . In Simple3ServiceBean, the user can access commonMethod, which has unrestricted access, the userMethod that is accessible by the ejb3user role and adminMethod which is accessible by ejb3admin role (see Security configuration in EJB2.1 deployment descriptors). All the other methods resulted in AccessException or EJBAccessException upon invocation.


Run-as and default subjects

In addition to configuring method permissions for a bean's methods, you can configure a Run-as role for the bean to specify the security identity with which the bean invokes other beans. This configuration is useful when a bean's method needs to invoke other beans with a different security identity than the security identity with which it is invoked, e.g. a message-driven bean method, which is invoked with no security identity, invoking a secured session-bean method. You configure the security credentials that constitute the subject for run-as role security in the deployment plan.

In Community Edition releases prior to 2.0, security configuration for run-as and default subjects was constructed using the principals and credentials specified using default-principal tag and designated-run-as attribute of principal. Starting from Community Edition 2.0, all security flows from subjects resulting from logging into a security realm. To use these subjects, you need to supply login information for each such subject. This login information is captured in a credential store.


Credential store

Community Edition provides an implementation of credential store, namely SimpleCredentialStoreImpl that enables configuring a credential store using XML in the deployment plans. Listing 11 shows the credential store we used in the sample applications in this article.

Listing 11: Credential Store gbean
<gbean name="SampleCredentialStore" 
      class="o.a.g.s.credentialstore.SimpleCredentialStoreImpl" ...>
    <xml-attribute name="credentialStore">
        <credential-store 
              xmlns="http://geronimo.apache.org/xml/ns/credentialstore-1.0">
            <realm name="SampleSecurityRealm">
                <subject>
                <id>dwuser1-subject</id>
                    <credential>
                        <type>o.a.g.s.credentialstore.NameCallbackHandler</type>
                        <value>dwuser1</value>
                    </credential>
                    <credential>
                        <type>o.a.g.s.credentialstore.PasswordCallbackHandler</type>
                        <value>user1</value>
                    </credential>
                </subject>
                <subject>
                    <id>dwuser2-subject</id>
                    ...
                </subject>
                <subject>
                    <id>dwuser3-subject</id>
                    ...
                </subject>
                <subject>
                    <id>dwadmin-subject</id>
                    ...
                </subject>
            </realm>
            <realm name="AnotherRealm">
                <subject>
                ...
                </subject>
                ...
            </realm>
        </credential-store>
    </xml-attribute>
</gbean>

Here, the name attribute of the realm element specifies the name of the security-realm that you use to create the subject. The id element under the subject element specifies an ID for the subject, which can be used in combination with the security-realm name when configuring run-as and default subjects as we show later.

You use the credential element under the subject to configure the log-in information for the security-realm. In Listing 11,we obtain dwuser1-subject logging into SampleSecurityRealm using user name dwuser1 with password user1. Currently Community Edition provides callback handlers for name and password that are sufficient for using security realms that need name and password to authenticate. For using other security realms with the credential store, for example ones that use digital certificates, you need to implement the required callback handlers. Also, the credential stores can be per application, or you can have one credential store that is used by all applications.


Configuring application to use a credential store

You specify the credential store to be used by an application in the security configuration in the application's deployment plan. Listing 12 shows the security configuration of one of the sample applications used in this article.

Listing 12: Security configuration showing credential-store-ref
<security>
    <credential-store-ref>
        <name xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2">
             SampleCredentialStore</name>
    </credential-store-ref>
    ...
</security>

In this example the name element under credential-store-ref specifies the credential store to be used by the application. Note that this value matches the name attribute of the credential store gbean shown in Listing 11.


Configuring run-as and default subjects

You specify the run-as and default subjects for the application in the security configuration in the application's deployment plan. If a run-as subject is not configured for any role, the configured default-subject will be used instead. Listing 13 shows the run-as and default subject configuration of one of the sample applications used in this article.

Listing 13: Security configuration showing run-as and default subjects
<security>
    ...
    <default-subject>
        <realm>SampleSecurityRealm</realm>
        <id>dwuser1-subject</id>
    </default-subject>
    <role-mappings>
        <role role-name="ejb3user">
            <run-as-subject>
                <realm>SampleSecurityRealm</realm>
                <id>dwuser3-subject </id>
            </run-as-subject>
            <principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal" name="UserGrp"/>
        </role>
        <role role-name="another">
        ...
        </role>
        ...
    </role-mappings>
</security>

The default-subjectelement under the security element configures the default subject used by the application. The realm element under default-subject specifies the security-realm, and the id element specifies the ID of the subject as configured in the credential store. Notice that value specified for the realm under default-subject matches the name attribute of the realm element in Listing 11. Also, note that the value specified for the id under default-subject matches one of the subject's id in Listing 11.

The run-as-subject element in the role element under role-mappings configures the run-as subject for that role. Listing 13 shows run-as subject configured for the ejb3user role. Notice that value specified for realm under run-as-subject matches the name attribute of the realm element in Listing 11. Also, note that the value specified for id under run-as-subject matches one of the subject's id in Listing 11.


Sample EJB application with run-as

We have added two more session beans (Simple3ServiceBean2 and Simple3SeviceBean3) that in turn invoke the corresponding methods in Simple3ServiceBean. We configured Simple3ServiceBean2 to run as ejb3user role. Simple3ServiceBean3 is not configured with a run-as role. Listing 14 shows the Simple3ServiceBean2 bean class.

Listing 14: Simple3ServiceBean2 class
@Stateless
@DeclareRoles(value = {"ejb3user", "ejb3admin"})
@RunAs("ejb3user")
public class Simple3ServiceBean2 implements Simple3Service2 {

	  @EJB
	  private Simple3Service simple; // Simple3Service injected here
	
        @PermitAll
	  public String commonMethod() {
          Object temp;
          try {
              temp = simple.commonMethod();
          } catch(Throwable t) {
              temp = t;
          }
          return logCall("commonMethod") + "::" + temp;
	  }

        @RolesAllowed({"ejb3user"})
	  public String userMethod() {
            ...
	  }

        @RolesAllowed({"ejb3admin"})
	  public String adminMethod() {
            ...
	  }
	  
        @DenyAll
	  public String noaccessMethod() {
            ...
	  }
	  
      private String logCall(String method) {
            ...
	  }
}

In this example, we used the @RunAs annotation with the ejb3user role to configure the run-as role for Simple3ServiceBean2. With this configuration, the invocation of methods on Simple3Service use the run-as-subject as specified in the deployment plan. Note that the run-as-subject for the ejb3user role is specified as dwuser3-subject (see Listing 13).


Run the sample application with run-as EJB security

  1. Navigate to the Deploy New portlet.
  2. Deploy simple-ejb-app-w-runas.jar provided in the samples. Make sure to select the Redeploy application option before clicking Install.
  3. Navigate to the Web App WARs portlet and start dw/simple-web-app/1.0/war.
  4. Access http://localhost:8080/simple-web-app . Scroll down to the RunAs section which shows the screen in Figure 6.
    Figure 6: Web application home page accessing EJBs with run-as
    Screen shot of home page with run-as

    Notice under the RunAs section that the commonMethod in Simple3ServiceBean2 is invoked as an Unauthenticated user, but, in turn the commonMethod in Simple3ServiceBean is invoked as dwuser3 as configured by run-as-subject. Since Simple3ServiceBean3 is not configured with run-as role, the commonMethod in Simple3ServiceBean is invoked as an Unauthenticated user.

  5. Access http://localhost:8080/simple-web-app/customer/. Login with name dwuser1 using password user1. Scroll down to the RunAs section, which shows the screen in Figure 7.
    Figure 7: Web application customer page accessing EJBs with run-as
    Screen shot of customer page with run-as

Notice that under the RunAs section the commonMethod and userMethod in Simple3ServiceBean2 are invoked as dwuser1, the current user logged into the Web application. However, in turn the commonMethod and userMethod in Simple3ServiceBean are invoked as dwuser3 as configured by run-as-subject. Since Simple3ServiceBean3 is not configured with run as role, the commonMethod and userMethod in Simple3ServiceBean are invoked as dwuser1.


Configuring entity bean security

You can configure entity bean security using the deployment-descriptor and security annotations the same way as we did for session bean security. Listing 15 shows the assembly-descriptor from a sample EJB application with an entity bean.

Listing 15: Assembly-descriptor
    <assembly-descriptor>
       <security-role>
           <description>Bank Manager</description>
           <role-name>manager</role-name>
       </security-role>
       <method-permission>
           <role-name>manager</role-name>
           <method>
               <ejb-name>MyBank</ejb-name>
               <method-name>create</method-name>
           </method>
       </method-permission>
   </assembly-descriptor>

In this example, we configured the create method on the Home interface of MyBank entity bean to be accessible only by the manager role.


Run the Entity bean sample application

The MyBankEJB sample application provided in the samples contains a single EJB2.1 entity bean named MyBank. We configured the create method in the bean's LocalHome and Home interfaces to be accessible only by the managerrole.

Follow these steps to run the application:

  1. Navigate to the Deploy New portlet.
  2. In the Archive field, browse to <SAMPLES_HOME> and select bank-db-pool.rar.
  3. Click Install to deploy the database pool used by the MyBankEJB application.
  4. In the Archive field, browse to <SAMPLES_HOME> and select MyBankEJB.jar.
  5. Click Install to deploy the MyBankEJB application.
  6. In the Archive field, browse to <SAMPLES_HOME> and select MyBankWeb.war.
  7. Click Install to deploy the MyBankWeb application.
  8. Access http://localhost:8080/MyBankWeb.

    Notice that the displayed page shows that an exception occurred in the Create an account section, because the user has not logged in.

  9. Now access http://localhost:8080/MyBankWeb/manager

Notice that the displayed page now shows that account creation is successful. It succeeded because the page is configured, using run-as role, to access the MyBank bean with the user ID dwadmin which maps to the manager role as configured in the MyBankEJB deployment plan.


Configuring Message-driven bean security

Unlike session and entity beans, message-driven beans are not invoked by other beans or client applications. They are invoked by a JMS listener when a message arrives on the input destination the listener is monitoring. Message-driven beans can invoke other session and entity beans. To invoke secure EJBs from a message-driven bean, the message-driven bean needs to be configured with a run-as role. For EJB2.1 message-driven bean, you can configure run-as role using the security-identity element in the deployment descriptor. For EJB3 message-driven bean, you configure run-as role cusing an @RunAs annotation.


Run the Message-driven bean sample application

To demonstrate the run-as security for an EJB3 message-driven bean, we have provided an application (jms-mdb-sample-ear-2.1.0.1.ear) in the sample. The application consists of one message-driven bean called OrderRecvMDB and a stateless session bean called Simple30ServiceBean. We configured the session bean's userMethod to be accessible by the ejb3user role, and the OrderRecvMDB bean with run-as role ejb3user. In the deployment plan, the security configuration specifies a run-as-subject dwuser1-subject for the ejb3user role. Listing 16 shows the OrderRecvMDB bean class:

Listing 16: OrderRecvMDB bean class
import javax.annotation.security.RunAs;
...

//
// MessageDrivenBean that listens to items on the
// 'OrderQueue' queue and processes them accordingly.
//
@MessageDriven(activationConfig = {
       @ActivationConfigProperty(propertyName="destinationType", 
           propertyValue="javax.jms.Queue"),
       @ActivationConfigProperty(propertyName="destination", 
           propertyValue="OrderQueue")
   })
@RunAs("ejb3user")               
public class OrderRecvMDB implements MessageListener {
	
	@EJB
	private Simple30Service simple; // Session bean is injected

	/*
     * Process a message.
     * 
     * @param message The message to process. 
     */
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("Order Received \n"+ textMessage.getText());
            simple.userMethod();
        } catch ( JMSException e ) {
            e.printStackTrace();
        }
    }
}

Follow these steps to run the application:

  1. Navigate to the Deploy New portlet.
  2. In the Archive field, browse to <SAMPLES_HOME> and select jms-mdb-sample-ear-2.1.0.1.ear.
  3. Click Install to deploy the sample application.
  4. Access http://localhost:8080/order .
  5. Enter the field values and click Order.

Notice that the server console window displays the order received along with the details on the security identity dwuser1 with which the userMethod in Simple30ServiceBean is invoked.


Conclusion

We have created EJB2.1 and EJB3 session beans, an EJB2.1 entity bean, and configured access permissions for the bean methods using deployment descriptors and security annotations. We have also configured a run-as role for session and message-driven beans, and created the necessary artifacts like a credential store to deploy the EJB applications that use this security configuration. We have also demonstrated EJB security using sample Web applications to invoke the EJBs.


Acknowledgements

Thanks to Phani Madgula for reviewing this material.


Download

DescriptionNameSize
Sample source codesamples.zip1.6MB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Open source
ArticleID=354720
ArticleTitle=Configuring EJB application security using WebSphere Application Server Community Edition
publish-date=11262008