In this article we will look in depth at EJB Security that a developer will need to know for the Component Developer Exam. We will first focus on both authentication and authorization as well as users, groups and roles and their function within EJB Security. This is closely linked to our previous article, Tutorial:Review of EJB Transaction for the Component Developer Exam since both transactions and security are crosscutting concerns. Finally we will look at how to overlay security into the TudoList application.

Introduction of EJB Security

EJB Security is based around role-based security. In order to be able to provide security in the age of sophisticated cyber-world hackers, phishers, and identity/data thieves, it is essential for EJB to have a security model that is elegant, flexible, and portable across heterogeneous systems. The basic security model involves the concepts of authentication and authorization, users, and groups that can be implemented both declarative and programmatic security in EJB 3. Letís start by looking at authentication and authorization.

Authentication vs. Authorization

In order to properly secure an application, there are two primary functions that need to be fulfilled. They are authentication which is the first thing that needs to be performed to properly identify and validate the user, and second is authorization which determines whether the identified users is allowed to have access to a particular resource.

Tutorial: Review of EJB Security for the Component Developer Exam-a11-ejbsecurity.jpg
Figure: EJB Security

Authentication

Authentication is the process of validating the user identity of someone who wants to interact with the application. By authenticating the user, it verifies that the user actually exists in the system and has provided the proper credentials. These credentials can be something as simple as a password or something more sophisticated like a RSA key. Security would be meaningless if any person could log onto a system with a false identity.

Once a remote client logs into an EJB system, is has a security identity associated with a it so that is can use bean to do useful work. When a bean is invoked by a client, the EJB server implicitly passes the clientís identity to the method invocation. The EJB container that handles the method invocation, checks the identity to ensure it is a valid client and that it is allowed to invoke the target method.

Although the EJB specification defines how security information is propagated from a client to a server, for the most part is does not define how authentication should be implemented. So there is no information in the specification as to how the client obtains and associates the identity and credentials of the user with an method invocation nor is the any information as to how the application server stores and retrieves authentication information. These details are all left to the vendor as to how to pack and deliver these services on the client and server.

The JNDI API is used by most application servers for implementing authentication when a remote EJB method is invoked. This allows the client to provide authentication information to access a server or resource in the server. An example of this is when a client wants to access a server in order to initiate a JNDI connection. The following code below shows how this can be done using a clientís username and password for authentication:

Java Code: Programmatically authenticating for JNDI
   properties.put(Context.SECURITY_PRINCIPAL, "username"); 
   properties.put(Context.SECURITY_CREDENTIALS, "password");
   Context ctx = new InitialContext(properties); 
   Object ref = jndiContext.lookup("TodoBusinessBean/remote"); 
   TodoRemoteBusiness remote = (TodoRemoteBusiness)ref;
Here the username and password are provide by the client in order to authenticate the user with the JNDI InitialContext. The authentication credentials are then propagated to the server internally when calls are made to remote EJBs. For a more robust authentication mechanism, most application servers will use the Java Authentication and Authorization Service (JAAS) specification. JAAS provides a rich API for doing authentication and authorization.

Authorization

Once a user is authenticated, the person can then be allowed access to resources available in the application with which they can interact. Authorization is the process of determining whether a user is permitted access to a particular resource or task. In an open system like a online retail store, an authenticated user can access almost resource. In a corporate security environment, most systems will restrict access to resources based on user identity. This is different from an online retail store where many resources (related to shopping for products) might be accessible to all. In corporate settings most resources can only be accessed by limited group of people. There are some lesser concepts that we will look at now that is tied to primarily to authorization but is also relevant for authentication.
client is allowed to invoke the target method. The other security concepts are the users, groups, and roles and how they are important to providing robust security for your application.

Users, Groups, and Roles

To be able to perform efficient and maintainable authorization, it is best if one organizes users into groups. This allows for more efficient management of all resources since each resource is associated with a few groups who are allowed access rather than a list of all the users who are permitted to access it. This would easily become a major problem for an administrator in a complex system for a large company since managing resource access with a list of a few groups is alot easier than managing a list with hundreds of thousands of users.

Roles are closely related to the concept of group. For EJB applications, roles play a more crucial role than users and groups. This is because often we donít know the exact operational conditions in which the application will be deployed or used once it has been purchased by the customer. Therefore since you cannot know in advance what the system administrator will choose for group names, we use roles to define what a user in a group holds in relation to the application. In EJB, method granularity is used for assigning access control. This is done on a per-role basis. This facilitates the authentication process to have a separate configuration from the authorization. The roles for authorization are logical roles since they donít relate directly to users, group or other security identities in a particular operational environment. EJB security roles then are mapped to real-world user groups and users when the EJB is deployed. This facilitates the portability of beans for each deployment. Within a companyís IT landscape, there will be many applications that a user will be required to use in order to be able to efficiently work and collaborate with others. In the companyís operation environment, the system administrator for each application or possibility for all of the applications will determine what system group gets map to what application role for each application in their environment.

As authorization is defined in the EJB specification, you can declare the roles that are accessed programmatically in your code bas and then assign permissions for each method of a class. Again as with most other configuration, you can do this either with annotations or by using the ejb-jar.xml deployment descriptor. In Java Enterprise Environment, vendors provides a series of administrative interfaces to accomplish this work.

Securing TudoList

In order to demonstrate security, we will secure access to the TudoList application. This will be add a security layer on top of our business methods to ensure secure access to the TudoList functionality.

EJB 3 and EJB Security

As we mentioned before EJB Security is based primarily on the JAAS API. This is a key area for any component developer to grasp for the part of the exam on security. JAAS decouples the authentication system from your application by using its well-defined, pluggable API. Similar to other API, the JAAS API is used by the Java EE application to talk to the underlying authentication systems like Lightweight Directory Access Protocol (LDAP), such as Microsoft Active Directory or Oracle Internet Directory (OID) using a vendor plug-in. Because of JAAS API, it is possible to easily swap between authentication systems by changing the JAAS plug-ins without any code change.

JAAS is also used for performing authorization on both the web and EJB tiers. It is designed so that the steps for both the authentication and authorization can be performed at any Java EE tier. Since most Java EE applications are web accessible and share an authentication system across tiers as well as the application server, JAAS fully leverages this access once a user or entity is authenticated at any Java EE tier. The benefit of this is that rather than being forced to repeat the authentication step, the authentication context can be passed through tiers whenever possible. The means of doing this is the JAAS javax.security.Principal interface. The Principal object represents this sharable, validated authentication context. This is shown in the figure below:

Tutorial: Review of EJB Security for the Component Developer Exam-a11-jaas.jpg
Figure: Java Authentication and Authorization Service

The user enter the application via the web tier. When the user provides authentication information, the web tier gathers this information and authenticates the supplied credentials via JAAS against an underlying security system. When the user is successfully authenticated the system returns a valid user Principal which has been associated with one or more roles. Each time the user tries to access a secured web/EJB tier resource, the application server will checks if the principal/role is authorized to access the resource by transparently passing the Principal from the web tier to the EJB tier as needed. Next letís look at the basics of web tier security to serve as a starting point for further investigation before diving into authorization management in EJB 3.

Authentication and Authorization in the Web Tier

For web tier authentication and authorization, many of the low-level details are hidden from the developer. All that is required is to tell the servlet container what resources to secure, how to secured them, how to gather authentication credentials and what roles have access to secured resources. The servlet container will handle the details under the cover. You just need to configure the login-config and security-constraint elements of the web.xml file. The listing below shows an example of how to do this:

XML Code: web.xml security configuration
<login-config> 
   <auth-method>BASIC</auth-method> 
   <realm-name>TudoListRealm</realm-name>
</login-config>

... 
<security-constraint>
   <web-resource-collection> 
      <web-resource-name>
      TudoList Administration
     </web-resource-name> 
     <url-pattern>/admin/*</url-pattern>
   </web-resource-collection> 
   <auth-constraint>
      <role-name>TLA</role-name> 
   </auth-constraint>
</security-constraint>
In the listing above, we are using the BASIC authentication mechanism. BASIC is the simplest authentication mechanism. It uses an HTTP headerĖbased authentication scheme that induces the web browser to gather username/password information using a built-in prompt. There are other popular authentication mechanisms. They include FORM which is essentially the same as BASIC except that you create an HTML form rather than use the built-in prompt from the web browser, and CLIENT-CERT which is an advanced form of authentication that bypasses username/password prompts altogether. Instead in CLIENT-CERT the client sends a public key certificate stored in the client browser to the web server using Secured Socket Layer (SSL) and the server authenticates the contents of the certificate. These credentials are then validated by the JAAS provider.

The next part is to specify the realm against which the container should authenticate. A realm is a container-specific abstraction used by a JAAS-driven authentication system. In this case, we specify that all URLs that match the pattern /admin/* are to be secured.

The last part is to specify that only principals validated with the TLA (for TodoList Admin) role can access the secured pages. This is the standard way to secure a web site using JAAS using declarations. If you want to do it programmatically, it essentially follows the same pattern as providing programmatic security for EJB applications.

Authentication and Authorization in the EJB Tier

The security features discussed here only apply to session beans and message driven beans. It does not apply to JPA entities. Setting up authentication in the EJB tier is similar in many aspects to transaction management. It can be done either programmatically or declaratively. Depending on the means that you choose it will affect the level of control that you have over the authentication process. Setting up authorization in an EJB tier is very simple. Similarly to the web tier, it is based on checking the authenticated Principle against an EJB resource instead of a web resource. If the authenticated Principalís role allows access to the EJB resource, the method will be invoked. If the Principal doesnít have the role permitting access, it will not allow access.

Declarative Security in TodoList

Here we apply the authentication rules to the TodoListBusinessBean that includes the createTodoList method. Now, only TLAs are allowed to use this method:

Java Code: Declarative security configuration for TodoListBusiness Bean
@DeclareRoles("READER", ďLEADERĒ, "TLA", "ADMIN")	
@Stateless 
public class TodoListBusinessBean implements TodoListBusiness {
   @RolesAllowed("LEADER, TLA, ADMIN") 
   public void createTodoList(TodoList todoList) {...}

   @PermitAll 
   public TodoList findTodoList(String listId) {...}
}
In this listing we have used some of the common security annotations defined by Java Platform Specification JSR-250. These annotations are:
  • @DeclareRoles - You use this to declare the security roles that you want to be used in your application, EJB module, EJB, or business methods.This annotation can be applied at the method or the class level and is given in the form of an array of role names. In our example, the TodoListBusinessBean we define the following roles, READER, LEADER, TLA and ADMIN. This can also be done using deployment descriptors. if for some reason we neglect to do this, the container will automatically create a list of roles by inspecting the @RolesAllowed annotation. Your system administrator must remember to map each role to groups defined in the runtime security environment when the application is deployed
  • @RolesAllowed - is key for declarative security management. It can be applied to an entire class or a EJB business method. When done on a class level, the roles are applied for all methods in the EJB. If it is done on a method level, it only applies for that method. You still have the flexibility to override class-level settings by applying the annotation at the method level in order to further restrict access to certain methods. In our listing we specify that only LEADER, TLA and ADMIN roles be allowed to create TodoLists through the createTodoList method.
  • @PermitAll - the @PermitAll annotation is used mark an EJB class or a method so that it can be invoked by any role. The @PermitAll annotations is used on the findTodoList allowing all authenticated users access to this method. Use this annotation sparingly, since it can create gaping security holes in your system.
  • @DenyAll - this annotation does exactly the opposite of @PermitAll. It will render functionality either the class or the method level inaccessible by any role. This is useful when your application is deployed in an environment that you didnít anticipate and you want to invalidate methods or classes that might be inappropriate for a particular environment without changing code. Remember that when this annotation is applied at the method level it will override bean-level authorization settings.

Note that the three security annotations, @PermitAll, @DenyAll, and @RoleAllowed, cannot simultaneously be applied to the same class or the same method. There is one other annotation that you need to know. That is @RunAs.

@RunAs
When you need to dynamically assign a new role to an existing Principal in order to invoke an EJB method, we use the @RunAs annotation. This is useful if youíre invoking another EJB from within your method but the other EJB doesnít have the same authorization role for itís method as your Principal. The role that is assumed can be either more restrictive, lax, or neither. In TudoList, it might be necessary for a createTodo method to invoke a createTodoList method in order to create a new TodoList for a new Todo. If the security is structured such that anyone authenticated can create a Todo but as we know from the previous listing, LEADER, TSA and ADMIN can create TodoList, we could do the following:

Java Code: Example of @RunAs use
@RunAS("LEADER") 
@RolesAllowed("USER") 
createTodo(String listId, Todo todo) {...}
This will temporarily assign a LEADER role to USER when someone wants to create a new Todo so that if necessary it can create a new TodoList. This annotation is to be used sparingly as it can open up security holes in your application.

As you can see, declarative security gives you access to a powerful authentica- tion framework while staying mostly out of the way. The flexibility available to you through the relatively small number of relevant annotations should be apparent as well. If you have ever rolled out your own security or authentication system, one weakness might have crossed your mind already.

Programmatic Security in TodoList
There are times where declarative security will not be sufficient when you need to provide security for an individual or to change a method behaviour based on the current Principalís role. In that case, you will need programmatic security. Programmatic security provides direct access to the Principal and access to itís role in the code. The functions for these are available through the EJB context. Below is an modification of the listing for TodoListBusinessBean using programmatic security.

Java Code: Programmatic Security for TodoListBusinessBean
@Stateless 
public class TodoListBusinessBean implements TodoListBusiness {
   @Resource 
   SessionContext context;
   ...
   public void createTodoList(TodoList todoList) {
         if (!context.isCallerInRole("TLA")) { 
            throw new SecurityException("No permissions to create todo");
         }
         ...
      }
      ...
   }
The process is to first inject the EJB context , then to invoke the isCallerInRole method of the EJBContext to check if the underlying authenticated principal has the TLA role. If it is false, we throw a java.lang.SecurityException notifying the user they are not authorized to call this method. Otherwise, the createTodoList method proceeds as normal.

The programmatic security has two methods for doing the majority of the work. They are:
  • Principal getCallerPrincipal()
  • boolean isCallerInRole(String roleName)

As we have already demonstrated the isCallerInRole method. It is checks to see if any of the roles from the Principal retrieved by the EJB context in the current thread matches the name you provided. The getCallerPrincipal method provides direct access to the java. security.Principal which represent the current authentication context. The only method you will tend to use on the Principal interface is the getName. It obviously returns the name of the Principal. In most cases, this will be the login name of the validated user. An example of using getCallerPrincipal and the Principal interface method is shown below:

Java Code: Example of getCallerPrincipal use
String callerName = context.getCallerPrincipal().getName();
Note there is no guarantee exactly what the Principal name might return. Depending on the environment, you could get the role name, group name, or any other arbitrary String that is determined by the authentication system. Check the documentation of your particular security environment before using it.


Using Interceptors with Programmatic Security

One major problem with programmatic security management is the mixing of security code with business logic as well as the hardcoding of role and Principal names. In EJB 3 the introduction of interceptors can help to alleviate this problem. As interceptors can be invoked before and after any EJB business method. This facilitates the application of security as a crosscutting concerns that need not be duplicated in every method. If we re-implement the previous listing of the programmatic security for the TodoListBusinessBean using interceptors, we would have the following:

Java Code: Security interceptor with TodoListBusinessBean
public class SecurityInterceptor {
   @AroundInvoke
   public Object checkUserRole(InvocationContext context)
         throws Exception { 
      if (!context.getEJBContext().isCallerInRole("TLA")) {
         throw new SecurityException( "No permissions to create TodoList");
      } 
      return context.proceed();
   }
}

@Stateless 
public class TodoListBusinessBean implements TodoListBusiness {
      @Interceptors(com.acme.tudo.security.SecurityInterceptor.class) 
      public void createTodoList(TodoList) { ... }
We have created a SecurityInterceptor class with a method checkUserRole that is designated as @AroundInvoke. checkUserRole checks if the Principal has a role TLA. If not, a SecurityException is thrown. The @AroundInvoke means that checkUserRole will be invoked whenever a method is intercepted. The TodoListBusinessBean specifies the SecurityInterceptor class as the interceptor for the createTodoList method.

This approach helps by separating the business logic from the code dealing with security into the interceptor. You can then reuse these interceptors across the application. This works very well for small application but become convoluted as the application grows larger. The recommended approach is for you to use declarative security management via annotations or deployment descriptors or a combination of both.

OK thatís it for basic security concepts using declarative and programmatic security management. As well this is the end of the series of articles on what you need to know for the component developer exam. I wish you the best for the exam.