Anda di halaman 1dari 14

Implementing J2EE security using JAAS on JBOSS

By Ashwin Kumar Karkala

Introduction......................................................................................................................................... 2 Introduction to JAAS............................................................................................................................. 2 Security mechanisms in JBOSS .............................................................................................................. 3 LoginModule implementation in JBOSS................................................................................................... 4 Custom LoginModule implementations.................................................................................................... 4 Securing a Web application in JBOSS ................................................................................................... 5 Securing an EJB application in JBOSS .................................................................................................... 6 Some advanced topics ......................................................................................................................... 7 JAAS chaining ................................................................................................................................. 7 LDAPExtLoginModule........................................................................................................................ 7 Pluggable security manager for JBOSS ............................................................................................... 7 Standalone JBOSS clients ..................................................................................................................... 8 JAAS login on the client side ............................................................................................................. 8 Using JNDI .................................................................................................................................... 11 Some common pitfalls in JBOSS .......................................................................................................... 12 HTTPServletRequest.getUserPrincipal()............................................................................................... 12 JBOSS SimplePrincipal and SimpleGroup Vs Custom Principal and Group............................................ 12 JBOSS-provided SimplePrincipal and SimpleGroup Implementations .................................................... 12 Custom implementations ................................................................................................................. 12 JBOSS standalone client ..................................................................................................................... 12 Acknowledgements ............................................................................................................................ 13 About the author................................................................................................................................ 13 For more information.......................................................................................................................... 14 Call to action .................................................................................................................................... 14

Introduction
This paper introduces the Java Authentication and Authorization Service (JAAS). The paper also explains some of the options available to you as a developer to help you enable security on the JBOSS Application Server, version 4.0.2, and discusses how to choose between these options. It discusses various aspects of J2EE security, common pitfalls found during JBOSS implementations and mechanisms available for overcoming these pitfalls. Finally, this paper provides information on how to access secured applications from outside the JBOSS container using standalone clients.

Introduction to JAAS
JAAS delivers a framework for providing authentication and authorization for all the Java applications. Authentication is a mechanism to verify the client; authorization is a mechanism to ensure that the client has the permissions required to access a secured resource. At a high level, the steps to enable JAAS-based security are as follows:
1. Identify the resource that needs to be secured. For the purpose of this paper, lets consider a Web

application and an Enterprise Java Bean (EJB) application.

2. Identify a suitable security provider. The security manager that comes with JAVA 2 provides the

security. In the case of JBOSS, the security is provided by the JBOSS security manager.

3. Use a security implementation to secure the identified resources. 4. Make the clients of the secured resources aware of the security implementation and usage

mechanisms. This is important as it is expected that the client will provide some sort of identifier before allowing access to secured resources. The identifiers in most cases are either username/password combinations or digital certificates. The clients must be aware of the required identifier before accessing the resource and should provide it when required.

The JAAS classes that enable the above are: LoginModule: This is the security implementation that authenticates and authorizes the clients. A typical implementation involves validating the username/password combination. LoginContext: Using this LoginContext, the client will be able to perform a login. CallbackHandler and Callback: These are the classes that allow interaction/data-transfer between the clients and the LoginModule. The LoginModule uses a Callback class to request information from the clients. The CallbackHandler class on the client side provides the required information based on the type of Callback class. Principal and Group: The LoginModule populates identification information (for example, Name, Address, etc.) about the client into the Principal class and authorization information (role list) into the Group class. Subject: This is the result of a successful login. This contains the authenticated Principal and Group. A Subject can also be viewed as a secure representation of the client after authentication. The whole login process can be represented using a sequence diagram, as shown in Figure 1.

Figure 1. JAAS login sequence

1. The client initiates the login using the LoginContext. The inputs to the LoginContext are the

CallbackHandler and the type of login configuration to use. The LoginContext internally instantiates the LoginModule and calls the initialization method.

2. The client then calls login() on the context. This results in the LoginContext calling the login()

method of the LoginModule. The LoginModule would need some client verification information. This will be obtained using Callbacks. The CallbackHandler handles these Callbacks and provides the requested information. Note: The CallbackHandler is a client implementation that handles specific Callbacks. The handler must know the exact Callbacks (or have a list of all potential Callbacks) that the LoginModule uses so that it can provide the required information to the LoginModule.

3. The LoginModule verifies this information. If the information is invalid, then a LoginException is

thrown. If the information is correct, authorization information for the client is obtained. and authorization information into the Subject.

4. The LoginContext then calls the commit method. In this method, the LoginModule sets the principal 5. The LoginContext returns this authenticated information back to the client. 6. The client uses the Subject to access a protected resource.

Security mechanisms in JBOSS


The JBOSS application server provides pluggable security managers. The Web and the EJB Containers use the security managers to perform authentication and authorization. The JAAS-based security manager is the default security manager provided with JBOSS. Though it is easy to replace the security manager with a custom implementation, this is not recommended. Note: The JAAS security manager obtains the required configuration information from the loginconfig.xml file located in the conf folder.

The XML file provides a list of security domains that are available on the server. Each domain specifies a list of LoginModules that protect the domain. The list of LoginModules can be specified as required or optional. To gain access to the resources protected by a domain, the client must be able to satisfy all the LoginModules that are configured as required. If any of the required LoginModules are not satisfied, the client will not be able to access the resource. Any options to the LoginModule can be specified in a configuration file. These will be passed to the module during the call to initialize(). Note: Each security domain will be read by the JAAS security manager, converted into a SecurityDomainContext object, and bound in JNDI at java:/jass/<domain_name> An application can choose from one (and only one) of the configured security domains to protect itself from the client access.

LoginModule implementation in JBOSS


The JAAS security manager doesn't perform the authentication. Instead, it instantiates the LoginModules that performs the actual authentication and authorization. JBOSS provides LoginModules out of the box. Some of these LoginModules are: UserRolesLoginModule: This module reads the username, password and role information from files that are packaged with the applications. DatabaseServerLoginModule: This module reads the username, password and role information from the tables in a database. The database is accessed using JDBC and the JDBC driver needs to be available in the application classpath. LDAPLoginModule: This module requires the username and password. This is used to connect to LDAP as a means of verification. If successful, the roles are based on the group memberships of the user. This module is not very configurable as it doesnt expose enough configuration options to work with all LDAPs. BaseCertLoginModule: This module uses client certificates to perform authentication. It cannot provide role information. This is typically used in conjunction with one of the other LoginModules to obtain the role memberships.

Custom LoginModule implementations


If the available login modules in JBOSS are insufficient, we can provide a custom implementation of the login module. In most enterprise applications, the user and the role information is stored in LDAP. As the LDAPLoginModule that comes with JBOSS not extensible enough to search for the group memberships, we must provide a custom implementation of the LoginModule interface. We have a couple of options for doing so: Extend the abstract UsernamePasswordLoginModule: JBOSS provides an abstract UsernamePasswordLoginModule that is the super class for all Authentication and Authorization (A&A) based on the username and password. This can be extended to perform the required authentication against LDAP and to search for group memberships. Write an independent LoginModule: We could use this option if we dont want the LoginModule to use JBOSS specific classes and to remain totally portable. Lets look at the latter option with a sample. A custom implementation of the LoginModule interface involves implementation of the following methods:

initialize (Subject, CallbackHandler, Map, Map): This is called by the security manager after the object instantiation. The purpose of this method is for the LoginModule to initialize itself based on the configuration options. The example of these configuration options could either be (in case of LDAP) the LDAP server address that holds the user or the LDAP context where the roles can be searched. These options are specific to the LoginModule implementation and this determines its behavior. The Subject is used to store the Principal and role information after a successful login() and commit(). login(): This is the core method. This method is supposed to perform the authentication and get the authorization (role) information from the information store. However, its important to note that this method should not store the authentication and the role information in the Subject. This information must be stored in the Subject only in the commit method. commit(): This method is called only if all the required LoginModules in the security domain successfully execute the login() method. This method should store the A&A information in the Subject. logout(): This method is called when the client does a logout. Here, the implementation should delete the A&A information from the stored Subject. abort(): This method is called when the client aborts during a login. This method is used to free up any resources that are held by the implementation. In the case of the LoginModule implementations (JBOSS supplied or custom), the A&A information is stored in the Subject. The information is stored using implementations of the two interfaces. One interface is used for the user data and the other for specifying the role information. Interface java.security.Principal: A principal represents the information related to an authenticated client. Interface java.security.acl.Group: Implementation used to hold a collection of Principals under a common name. The interface provides methods to add and remove Principals and to query if a Principal is part of the group. Notes: java.security.acl.Group extends java.security.Principal. So in reality, all the information is stored in the form of a Principal. Any information about an authenticated client is stored using a Principal. Typically, this includes name, address, phone number, email etc. Its important to note that the role memberships are also Principals. In these cases, every role that the client belongs to is a Principal and all these Principals are collected into a group with a common name. In the case of JBOSS, for the JAAS security manager to be able to identify the principals that identify the role memberships, the principals need to be consolidated into a Group named Roles.

Securing a Web application in JBOSS


Lets examine what it takes to secure a J2EE web application in JBOSS. In this section, we will examine only the declarative security mechanisms; we wont cover programmatic security. Declarative security for a web application involves providing select access to web resources based on certain roles that the client is assigned. Note: In J2EE web applications, a web resource is secured based on the URL pattern and the HTTP method (GET, POST etc) used to access the resource.

In the web.xml file, collections of resources that can be accessed by certain roles must be defined along with the list of roles that can access the resources. An example of web.xml settings for declarative security is shown below:
<security-constraint> <!-- A collection of protected resources along with the access mechanism --> <web-resource-collection> <web-resource-name>Restricted to Secure role</web-resource-name> <description>Declarative security</description> <url-pattern>/secure/*</url-pattern> <http-method>HEAD</http-method> <http-method>GET</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>DELETE</http-method> </web-resource-collection> <!-- The list of roles that can access the resource. --> <auth-constraint> <role-name>Secure</role-name> </auth-constraint> </security-constraint>

Listing 1: jbossweb.xml settings for declarative security In the above example, all the resources with the URL pattern /secure/* are protected, and the client must belong to the Secure role to access these resources. Note: Any number of <security-constraint> tags may be defined in web.xml During application packaging, the administrator must choose the security domain that will protect the application. This is specified in the JBOSS specific deployment descriptor, jboss-web.xml. A sample jboss-web.xml is shown below:
<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>java:/jaas/securedomain</security-domain> </jboss-web>

Listing 2: jboss-web.xml settings to enable security for a web application The file lists the securedomain as the security domain that will provide A&A to the web application.

Securing an EJB application in JBOSS


Lets examine what it takes to secure a J2EE EJB application in JBOSS. As before, we will examine only the declarative security mechanisms. Declarative security for an EJB application involves providing select access to EJB methods, based on the roles that the client is assigned. As with web tier security, we need to group the EJB methods based on the roles that can access these methods. This is done using the <method-permission> tag in the ejb-jar.xml file. A sample extract is shown below:

<method-permission> <role-name>Secure</role-name> <method> <ejb-name>Fibo</ejb-name> <method-name>factorial</method-name> </method> </method-permission> <method-permission> <unchecked/> <method> <ejb-name>Fibo</ejb-name> <method-name>compute</method-name> </method> </method-permission>

Listing 3: ejb-jar.xml settings for declarative security In the above example, the method factorial in the EJB Fibo is available only to the client belonging to the Secure role. However, the method compute in the same bean is available to all the clients. During the application packaging, the administrator must choose the security domain used to protect the application. This is specified in the JBOSS specific deployment descriptor, jboss.xml. A sample jboss.xml is shown below:
<?xml version="1.0" encoding="UTF-8"?> <jboss> <security-domain>java:/jaas/securedomain</security-domain> </jboss>

Listing 4: jboss.xml settings to enable security for an EJB application

Some advanced topics


JAAS chaining
As mentioned earlier, JAAS allows chaining of multiple LoginModules under one security domain. In this case, the client has to satisfy all the LoginModules that are listed as required, in order to gain access to the resources protected by the domain. Note: In this case, to prevent each LoginModule from asking the client to provide (potentially) the same information, the module must honor the useFirstPass option. If this option is passed to a LoginModule, then it must try to read the information from the shared state Map (this Map is shared across all the LoginModules in a domain) before attempting to read it from the client. This option should be configured for all the LoginModules in a domain except for the first one.

LDAPExtLoginModule
As mentioned earlier, the LDAPLoginModule in JBOSS is not flexible. To overcome this, JBOSS has provided the LDAPExtLoginModule. This module is more flexible than the original and its use must be considered before writing a custom LoginModule. See http://wiki.jboss.org/wiki/Wiki.jsp?page=LdapExtLoginModule for more information on the LDAPExtLoginModule.

Pluggable security manager for JBOSS


As mentioned earlier, the JAAS security manager is available out of the box with JBOSS. However, it is possible to install a custom security manager. The JAAS-based manager is extensible because JAAS

itself provides considerable flexibility. Therefore, the use of an alternative security manager must be given great consideration. If you decide to go ahead, a custom security manger can be programmed by implementing the following interfaces: org.jboss.security.AuthenticationManager: As the name suggests, this is responsible for providing the authentication (and getting the role information from the info store). Note: The isValid() method in the interface is used to perform the authentication. org.jboss.security.RealmMapping: This interface maps principals from the operation environment (info store) to the application domain. The interface also provides a method to check if the client has a specific role. Notes: o The getPrincipal(Principal): Principal method is used to perform the mapping and the doesUserHaveRole(Principal, Set) : boolean is used to determine if the client has a specific role. The out-of-the-box org.jboss.security.plugins.JaasSecurityManager implements both the AuthenticationManager and the RealmMapping interfaces. A custom security manager can be installed by creating a class that implements the AuthenticationManager and the RealmMapping interfaces. A custom JMX service needs to be created and started during the JBOSS server startup. The service should instantiate the custom written class and bind it to JNDI. The EJBs and Web tiers can now use the custom security manager by pointing the JNDI location in the <security-domain> tag.

o o

org.jboss.security.SecurityProxy: This interface provides methods that permit or disallow the access to an EJB method. Notes: o o o The invokeHome() and the invoke() methods provide hooks to check whether or not the EJB method should be allowed to execute. The out-of-the-box org.jboss.security.SubjectSecurityProxy provides the implementation of the interface. An alternate proxy can be installed on a per EJB basis in the jboss.xml using the <securityproxy> tag at the XPATH /jboss/enterprise-beans/session.

Standalone JBOSS clients


Lets now look at ways to access a secured EJB from a standalone client.

JAAS login on the client side


Its important to note that the JBOSS standalone client is running in its own JVM. Thus, we cannot execute the Server LoginModule on the client side because the generated Subject would not be valid on the Server side. The login would be valid only if the credentials are transported over to the server side and a login were executed on the server side. To enable this, JBOSS provides a thin LoginModule for JBOSS clients aptly named ClientLoginModule. This module stores the authentication information in ThreadLocal variables. This ensures that the authentication data is available anytime on the current thread of execution. Notes: It also supports storage using Singleton objects. Multi-threaded standalone applications can pass this option to the LoginModule.

This module doesnt perform the actual A&A. It only stores the data to be passed along to the server during EJB invocation of create methods. The clients can now look up the EJB HOME interface in the Server JNDI tree. When the create method is called on this interface, the HOME interface implementation sends across the authentication information as well. The Security proxy on the Server side uses this authentication information to perform a JAAS login on the server side. Upon successful authentication and on the availability of sufficient roles with the client, the EJB invocation is allowed to pass through; otherwise, the security proxy on the server side throws a SecurityException which is transported back to the client and sent back to the caller of the create method. The sample code to execute a Client side Login is given below:
/** * Performs the JAAS client side login and returns the subject * @return * @throws LoginException */ public Subject login() throws LoginException { Subject ret = null; LoginContext lc = new LoginContext("other",new ClientCallBackHandler("username","password")); lc.login(); ret = lc.getSubject(); return ret; }

Listing 5: Sample JAAS login for standalone clients

/** * A sample implementation of the CallbackHandler Interface that handles * username and password callbacks */ private class ClientCallBackHandler implements CallbackHandler { private String user,pass; /** * Constructor that takes username and password */ public ClientCallBackHandler(String user, String pass) { this.user = user; this.pass = pass; } /* (non-Javadoc) * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[]) */ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { int len = callbacks.length; Callback cb; for(int i=0;i<len;i++) { cb = callbacks[i]; if(cb instanceof NameCallback) { NameCallback ncb = (NameCallback)cb; ncb.setName(user); } else if (cb instanceof PasswordCallback) { PasswordCallback pcb = (PasswordCallback)cb; pcb.setPassword(pass.toCharArray()); } else { throw new UnsupportedCallbackException(cb, "Dont know what to do with this!!"); } }//end of for-loop } }

Listing 6: The CallbackHandler used by standalone client

other { // jBoss ClientLoginModule org.jboss.security.ClientLoginModule required ; };

Listing 7: The JAAS configuration used by standalone client Note: The path to the auth.conf file must be given as a JVM argument using the D option as Djava.security.auth.login.config=<full_path_to_file> Now that the client side pseudo login is complete, lets examine how to use the Subject to call the EJB method.
Subject sub = fc.login(); Subject.doAs(sub,fc.new SimpleAction());

Listing 8: Using the client side subject to call a privileged action


/** * The privileged action that invokes the secured EJB */ private class SimpleAction implements PrivilegedAction { /* (non-Javadoc)

10

* @see java.security.PrivilegedAction#run() */ public Object run() { try { InitialContext context = null; Hashtable ht = new Hashtable(); String value = null; FiboHome home; Fibo bean; ht.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory"); ht.put(Context.PROVIDER_URL,"localhost:1099"); context = new InitialContext(ht); //Now get the home interface Object ref = context.lookup("ejb/tutorial/Fibo"); home = (FiboHome) PortableRemoteObject.narrow(ref, FiboHome.class); //This create method results in the client side auth data being transported over to the jboss server where the actual login takes place. bean = home.create(); int fact = bean.factorial(5); System.out.println("The factorial of 5 is:" + fact); double[] fib = bean.compute(10); System.out.println("The first 10 fibonacci numbers are:"); for(int i=0;i<fib.length;i++) { System.out.print((int)fib[i] + ","); } }catch(Exception e) { e.printStackTrace(); } return null; } }

Listing 9: The privileged action that calls the EJB methods Note: You can find a link to the complete Client at the end of the document.

Using JNDI

It is possible to avoid the explicit client side JAAS pseudo login by using a special connection factory to connect to the JBOSS server JNDI. This factory is org.jboss.security.jndi.LoginInitialContextFactory. The exact configuration of the factory is available at http://wiki.jboss.org/wiki/Wiki.jsp?page=LoginInitialContextFactory (this class executes the client side login). Note: The auth.conf is still required and the path must still be specified using the D option to the JVM. A sample code for using this factory is specified below.
Properties env = new Properties(); // Try with a login that should succeed env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.LoginInitialContextFactory"); env.setProperty(Context.PROVIDER_URL, "jnp://localhost:1099/"); env.setProperty(Context.SECURITY_CREDENTIALS, "iso*help"); env.setProperty(Context.SECURITY_PRINCIPAL, "akarkala"); env.setProperty(Context.SECURITY_PROTOCOL, "jwdomain"); InitialContext context = new InitialContext(env); Object ref = context.lookup("ejb/tutorial/Fibo"); FiboHome home; Fibo bean; home = (FiboHome) PortableRemoteObject.narrow(ref, FiboHome.class); bean = home.create(); int fact = bean.factorial(5);

11

System.out.println("The factorial of 5 is:" + fact); double[] fib = bean.compute(10); System.out.println("The first 10 fibonacci numbers are:"); for(int i=0;i<fib.length;i++) { System.out.print((int)fib[i] + ","); }

Listing 10: JNDI access mechanism for secured EJBs

Some common pitfalls in JBOSS


HTTPServletRequest.getUserPrincipal()
The getUserPrincipal() method defined in the HTTPServletRequest interface is used by the web clients to access the Principal called the resource. In the case of custom implementations of the LoginModule interface, it is likely that this method will return a null to JBOSS. To prevent this and to ensure that the correct Principal is available, a Group must be created with the name CallerPrincipal in the LoginModule. This group must be added to the Subject within the commit() method. As there can be any number of principals in an authenticated Subject, this indicates to the JBOSS to pick this as the principal to return when the getUserPrincipal() method is called.

JBOSS SimplePrincipal and SimpleGroup Vs Custom Principal and Group


As described above, JAAS requires that we use the Principal and Group interfaces to store the authentication and the authorization data. The two options given below discuss this.

JBOSS-provided SimplePrincipal and SimpleGroup implementations


JBOSS provides implementations of the Principal and Group interfaces. However, the use of these implementations binds us to JBOSS, which results in the LoginModule not being portable. Using these implementations is recommended only if a JBOSS provided LoginModule is being extended.

Custom implementations
This is recommended if a completely new LoginModule is written. However, when used with JBOSS, the following must be noted. While implementing the isMember(Principal) : boolean method of the Group interface, comparison must be made based on the String contained within the Principal rather than by directly checking for the Principal. The reason for this is that the Principals within the group might have a different implementation class compared to the implementation class of the method parameter. Therefore, although the Principals contain the same String within them, the result might be false (with a direct comparison). You can get a summary of the discussion I initiated on the JBOSS forums at the links below. EJB SecurityException even though roles are present (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=67345) Different Role check mechanism for EJB and Web? (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=67395)

JBOSS standalone client


Please visit http://devresource.hp.com/technical_papers/jaas_jboss/FiboClient.zip (ZIP, 2 KB) for a copy of the JBOSS standalone client. When prompted, use a text editor to view the file contents.

12

Acknowledgements
I would like to acknowledge my manager Prabir Goswamee, who inspired me to write this paper. I would also like to thank Sudarshan Murty for his technical assistance.

About the author


Ashwin Karkala has a Bachelors degree in Electronics and Communications from Sri Jayachamarajendra College of Engineering at Mysore. He is experienced in developing/integrating various applications in the manufacturing and outsourcing domain. He is working as a project lead with the J2EE practice at HP in Bangalore.

13

For more information


For Technical information for developers on working with HP Software products and solutions HP OpenView Management Software HP Partitioning Continuum, HP, 2006 Please see http://devresource.hp.com

http://managementsoftware.hp.com/ http://h20338.www2.hp.com/hpux11i/cache/3237520-0-225-121.html

Call to action
Enhance your ability to create managed applications by subscribing to the HP Software Partner News newsletter. White papers, program updates, marketing and technical tools and downloads, and technical tips are delivered monthly. Visit http://devresource.hp.com/drc/newsletters/subscriptions.jsp to subscribe.

All brand and product names are trademarks or registered trademarks of their respective companies.

2006 Hewlett-Packard Development Company, L.P. The information contained herein is subject to change without notice. The only warranties for HP products and services are set forth in the express warranty statements accompanying such products and services. Nothing herein should be construed as constituting an additional warranty. HP shall not be liable for technical or editorial errors or omissions contained herein.

Anda mungkin juga menyukai