JBoss.orgCommunity Documentation

Chapter 9. Identity Management - Working with LDAP

Table of Contents

9.1. Overview
9.2. Configuration
9.2.1. Connecting to the LDAP Server
9.2.2. Mapping Identity Types
9.2.3. Mapping Relationship Types
9.2.4. Mapping a Type Hierarchies
9.2.5. Mapping Groups to different contexts

The LDAP Identity Store allows a LDAP Directory to be used as a source of identity data. Most organizations rely on a LDAP Directory to store users, groups, roles and relationships between those entities. Some of them only store users and groups, others only users and so forth. The point is that each organization has its own structure, how data is organized on the server and policies to govern all that. That said, is very hard to get all different use cases satisfied given all those nuances.

To try to overcome that, the LDAP Identity Store provides a simple and easy mapping between the entries in your LDAP tree and the PicketLink types (IdentityType, Relationship and so forth), plus some additional configuration options that give you more control how the store should integrate with your server.

The store can be used in read-only or read-write mode. Depending on your permissions on the server, you should consider one of these alternatives, otherwise you can get errors when, for example, trying to add, update or remove entries from the server.

The list below summarizes some of the most important capabilities provided by this store:

  • Mapping IdentityType types to their corresponding LDAP entries and attributes.

  • Mapping Relationship types to their corresponding LDAP entries and attributes.

  • Mapping of parent/child relationships between the LDAP entries mapped to the same type.

  • Authentication of users based on username/password credentials.

  • Use of LDAP UUID attributes as the identifier for identity types. For each identity type in PicketLink we need to provide a single/unique identifier. The LDAP store uses the entryUUID and objectGUID (depending on your server implementation, of course) to identify each type.

But the LDAP Directory has also some limitations (schema limitations, restrictive usage policies) and because of that the LDAP Identity Store does not supports all the feature set provided by PicketLink. The table below lists what is not supported by the LDAP Identity Store:

The LDAP Identity Store can be configured as follows:

IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();


builder
    .named("ldap.config")
        .stores()
            .ldap()
                // connection configuration
                .baseDN("dc=jboss,dc=org")
                .bindDN("uid=admin,ou=system")
                .bindCredential("passwd")
                .url("ldap://localhost:389")
                // mapping configuration
                .mapping(Agent.class)
                    .baseDN("ou=Agent,dc=jboss,dc=org")
                    .objectClasses("account")
                    .attribute("loginName", "uid", true)
                    .readOnlyAttribute("createdDate", "createTimeStamp")
                .mapping(User.class)
                    .baseDN("ou=User,dc=jboss,dc=org")
                    .objectClasses("inetOrgPerson", "organizationalPerson")
                    .attribute("loginName", "uid", true)
                    .attribute("firstName", "cn")
                    .attribute("lastName", "sn")
                    .attribute("email", EMAIL)
                    .readOnlyAttribute("createdDate", "createTimeStamp")
                .mapping(Role.class)
                    .baseDN("ou=Roles,dc=jboss,dc=org")
                    .objectClasses("role")
                    .attribute("name", "cn", true)
                    .readOnlyAttribute("createdDate", "createTimeStamp")
                .mapping(Group.class)
                  .hierarchySearchDepth(4)
                  .objectClasses("group")
                  .attribute("name", "cn", true)
                  .readOnlyAttribute("createdDate", "createTimeStamp")
                  .parentMembershipAttributeName("member")
                .mapping(Grant.class)
                    .forMapping(Role.class)
                    .attribute("assignee", "member")
                .mapping(GroupMembership.class)
                    .forMapping(Group.class)
                    .attribute("member", "member");

The LDAP configuration provides a simple mapping between your identity types and their corresponding LDAP entries. The way you map your types have a huge impact on how the LDAP Identity Store performs its operations.

Usually, a mapping is done as follows:

IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();


builder
    .named("ldap.config")
        .stores()
            .ldap()
                .mapping(User.class)
                    .baseDN("ou=User,dc=jboss,dc=org")
                    .objectClasses("inetOrgPerson", "organizationalPerson")
                    .attribute("loginName", "uid", true)
                    .attribute("firstName", "cn")
                    .attribute("lastName", "sn")
                    .attribute("email", "mail")
                    .readOnlyAttribute("createdDate", "createTimeStamp")

For each mapping you need to provide the identity type being mapped (in the case above the User type) plus all information required to store the type and populate its properties from their corresponding LDAP attributes.

In the example above, we're considering that User entries are located at the baseDN "ou=User,dc=jboss,dc=org". The baseDN is a very important information, specially if you want to store information from a type instance. Beside that, the baseDN can have a huge impact on performance when querying your LDAP entries for a specific type, as the search will be more restrictive and consider only those entries located at the baseDN and sub entries.

Another important configuration is the objectClass list related with a type. The objectClass is very important when storing new entries in your LDAP server. Also, the objectClass helps the LDAP Identity Store to make better queries against your server by restricting which entries should be considered during the search based on the objectClass list you provide.

In order to store and retrieve attributes from the LDAP server, you need to map them to the properties of your type. The attribute mapping is pretty simple, you just provide the name of the property being mapped and its corresponding LDAP attribute name. An important aspect when mapping the attributes is that you should always configure an attribute as the identifier. In the example above, we're telling the LDAP configuration to consider the following attribute as an identifier:

.mapping(User.class)

  .attribute("loginName", "uid", true)