Wednesday, October 18, 2006

JBOSS LDAP Integration

By Sandrick Melbouci

This article provide a prototype of integration of J2EE applications such as Servlets/JSPs, EJBs, MDBs with LDAP (Lightweight Directory Access Protocol) for application authorization and authentication. This article identifies some key interfaces within JBoss and any J2EE container compliant application server that can be configured to provide a secured access. We will provide a declarative LDAP security model in such a way you can configure it at runtime.

Few things to take in consideration:
- J2EE uses the same authorization model for both web-based components (servlets and JSPs) and enterprise components (EJBs). The specification requires transparent propagation of security credentials within the J2EE environment, so that once a user has authenticated to any J2EE component, the same security information is used by all other components.
- J2EE application programming model insulates developers from mechanism-specific implementation details of application security. J2EE provides this insulation in a way that enhances the portability of applications, allowing them to be deployed in diverse security environments.
- In order to integrate authorization into an unknown authentication mechanism, J2EE specifications define a simple role-based security model for EJBs and Web components. the specification defines a number of terms about security:
- A realm is the J2EE term for the security policy domain that is a definition of the way in which a user is authenticated. In its simplest form, a realm is a list of users and a mechanism for authenticating those users. Basic HTTP authentication is known as the HTTP realm; a public key certificate (PKC) authentication such as SSL is a different realm.
- A principal is the name of a user within the authentication realm. Although the J2EE specification does not require the principal name to be the same as the user's login name, most (if not all) J2EE implementations use the username as the principal name.
- A role is a definition of the way a user will use the system. Typical roles will be user, administrator, manager, developer, researcher, and so on. Outside the J2EE domain, a role is usually implemented by assigning users to one or more authentication groups or granting privileges to user accounts.
- A role reference is the name of a role used within the code of a J2EE application. As part of the J2EE application environment definition (known as the deployment descriptor), every role reference must be mapped onto a real role. The decoupling of the coded role reference from the actual role helps improve portability of a J2EE component.

Before we define the LDAP schema (LDIF file), the following are the LDAP common terms you need to know in order to understand this configuration.
To configure LDAP, refer to LDAP Admin guide

DN: Distinguished Name
A distinguished name uniquely identifies an entry in the directory. A DN is made up of “relative” distinguished names of the entry and each of the entry's parent entries, up to the root of the directory tree. These names are usually separated by commas and optional spaces. For example: 'uid=JohnDoe, ou=People, dc=company, dc=com'.
ObjectClass
An objectclass is a formal definition of a specific kind of objects that can be stored in the directory. An objectclass is a distinct, named set of attributes that represents something concrete, such as a user, a computer, or an application.
LDAP URL
LDAP URL is a string that specifies the location of an LDAP resource. An LDAP URL consists of server host and port, search scope, baseDN, filter, attributes and extensions.
Schema
An LDAP schema defines a set or rules that specifies the types of objects that a directory may contain and the required and optional attributes that entries of different types should have.

More details can be found in LDAP Admin guide.

Now, Let's define our LDAP schema to support the J2EE role-based security. Below is the LDAP structure that defines our LDAP tree:

com
---company
------------People
-------------------admin
-------------------demo
------------Roles
------------------Administrator
------------------Users


This structure is orgonized into 2 main structures, People and Roles. People contain the users and Roles groups the users into group of roles. A role is defined above, it provides the permission level for a user.

The following is the LDIF schema that also defines our LDAP entries.


dn: dc=company,dc=com
dc: company
objectClass: top
objectClass: dcObject
objectClass: domain

dn: ou=Roles,dc=company,dc=com
ou: Roles
objectClass: top
objectClass: organizationalUnit

dn: ou=People,dc=company,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit

dn: uid=demo,ou=People,dc=conpany,dc=com
uid: demo
objectclass: person
objectclass: inetOrgPerson
cn: demo
sn: demo

dn: uid=admin,ou=People,dc=company,dc=com
uid: admin
objectClass: person
objectClass: inetOrgPerson
cn: Admin
sn: admin

dn: cn=Administrator,ou=Roles,dc=company,dc=com
cn: Admin
objectClass: top
objectClass: groupOfNames
member: uid=admin,ou=People,dc=company,dc=com

dn: cn=Users,ou=Roles,dc=company,dc=com
cn:Users
objectClass: top
objectClass: groupOfNames
member: uid=demo,ou=People,dc=company,dc=com
member: uid=admin,ou=People,dc=company,dc=com


Save this schema into a file called entries.ldif

You can load this file by running the command :
ldapadd -f entries.ldif -x -D "cn=Manager,dc=company,dc=com" -w secret

Manager is administrator of the LDAP

Check that your entries are loaded by executing the following command:
ldapsearch -x -b 'dc=company,dc=com' '(objectclass=*)'

We are done with LDAP.

This example has been tested with OpenLDAP. It should work with any other LDAP provider.

Now, we need to tell JBoss how to authorize and authenticate against the LDAP entries we have created.
For our example, we will secure the JBoss jmx-console. Similar thing can be applied to any web application.

We need to modify web.xml and add the security constraint.

web.xml

<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role Admin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Administrator</role-name>
</auth-constraint>
</security-constraint>


<security-role>
Administrator
</security-role>


As you can see, we wanted only the users having a role "admin"to access the console.


Now we will tell JBoss what security scheme to use. To do so, we need to add security-domain element into jboss-web.xml. We have called our security scheme "AuthPolicy".

jboss-web.xml
<jboss-web>
<security-domain>java:/jaas/AuthPolicy</security-domain>
</jboss-web>


The "AuthPolicy" security policy shall be defined in login-config.xml located in :
$JBOSS_HOME/server/{config}/conf .
{config} can be one minimal, all, default or you can define your own.


Now let's define an entry in the login-config.xml. Remember, we will to define the LDAP URL defined above.

login-config.xml

<application-policy name="AuthPolicy">
<authentication>
<login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required" >
<module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
<module-option name="java.naming.provider.url">ldap://localhost:389/</module-option>
<module-option name="java.naming.security.authentication">simple</module-option>
<module-option name="baseCtxDN">ou=People,dc=company,dc=com</module-option>
<module-option name="baseFilter">(uid={0})</module-option>
<module-option name="roleFilter">(member={1})</module-option>
<module-option name="rolesCtxDN">ou=Roles,dc=company,dc=com</module-option>
<module-option name="roleAttributeID">cn</module-option>
<module-option name="roleAttributeIsDN">false</module-option>
</login-module>
</authentication>
</application-policy>


I highlighted some attribute in red. These attribute should be mapped to your LDAP schema definition.

See it in action. Fire up JBoss, and then go to: http://localhost:8080/jmx-console.

References:
Security Trail in the Java tutorial, http://java.sun.com/docs/books/tutorial/security/index.html
Core Security Patterns, http://www.informit.com/bookstore/product.asp?isbn=0131463071&rl=1
JBoss Security Model, http://www.huihoo.com/jboss/online_manual/3.0/ch13s78.html
JBoss Login Module, http://wiki.jboss.org/wiki/Wiki.jsp?page=LdapLoginModule

1 comment:

Anonymous said...

Thank you great article. I applied it to Oracle LDAP server and worked like charm.