Managing User Identity using Custom LDAP in Activiti Engine

1. Implement LDAP query logic for the Activiti Engine
a) First implement the Activiti engine SessionFactory interface to create a factory class for the user manager.
public class LDAPUserManagerFactory implements SessionFactory {
private LDAPConnectionParams connectionParams;
public LDAPUserManagerFactory(LDAPConnectionParams params) {
this.connectionParams = params;
}

           @Override
public Class<?> getSessionType() {
return UserManager.class;
}
@Override
public Session openSession() {
return new LDAPUserManager(connectionParams);
}
}

b) Create LDAPConnectionParams class for providing ldap connection details to connect to ldap server

public class LDAPConnectionParams {
private String ldapServer;
private int ldapPort;
private String ldapUser;
private String ldapPassword;
// provide getters and setters for the above variables
}

c) Create LDAPUserManager which should contain the  communication and query logic for ldap server
public class LDAPUserManager extends UserManager {

private static final String USER_GROUP = “ou=users,o=system”;

private LDAPConnectionParams connectionParams;

public LDAPUserManager(LDAPConnectionParams params) {
this.connectionParams = params;
}

@Override
public User createNewUser(String userId) {
throw new ActivitiException(
“LDAP user manager doesn’t support creating a new user”);
}

@Override
public void insertUser(User user) {
throw new ActivitiException(
“LDAP user manager doesn’t support inserting a new user”);
}

@Override
public void updateUser(User updatedUser) {
throw new ActivitiException(
“LDAP user manager doesn’t support updating a user”);
}

@Override
public UserEntity findUserById(String userId) {
UserEntity user = new UserEntity();

StringBuilder searchQuery = new StringBuilder();
if (StringUtils.isNotEmpty(userId)) {

searchQuery.append(“(cn=”).append(userId).append(“)”); // it can be cn or uid depends on your ldap configuration in server

}
LdapConnection connection = LDAPConnectionUtil.openConnection(connectionParams);
try {

Cursor<SearchResponse> cursor = connection.search(USER_GROUP,
searchQuery.toString(), SearchScope.ONELEVEL, “*”);
while (cursor.next()) {
SearchResultEntry response = (SearchResultEntry) cursor.get();
Iterator<EntryAttribute> itEntry = response.getEntry()
.iterator();
while (itEntry.hasNext()) {
EntryAttribute attribute = itEntry.next();
String key = attribute.getId();
if (“uid”.equalsIgnoreCase(key)) {
user.setId(attribute.getString());

} else if (“sn”.equalsIgnoreCase(key)) {
user.setLastName(attribute.getString());

} else if (“cn”.equalsIgnoreCase(key)) {
user.setFirstName(attribute.getString());
}

}

}

cursor.close();

} catch (Exception e) {
throw new ActivitiException(“LDAP connection search failure”, e);
}

LDAPConnectionUtil.closeConnection(connection);

return user;
}

@Override
public void deleteUser(String userId) {
throw new ActivitiException(
“LDAP user manager doesn’t support deleting a user”);
}

@Override
public List<User> findUserByQueryCriteria(UserQueryImpl query, Page page) {
// TODO Auto-generated method stub
List<User> userList = new ArrayList<User>();
// Query is a UserQueryImpl instance
UserQueryImpl userQuery = (UserQueryImpl) query;
StringBuilder searchQuery = new StringBuilder();
if(StringUtils.isNotEmpty(userQuery.getId())) {
searchQuery.append(“(uid=”).append(userQuery.getId()).append(“)”);
} else if(StringUtils.isNotEmpty( userQuery.getLastName())) {
searchQuery.append(“(sn=”).append(userQuery.getLastName()).append(“)”);
} else {
searchQuery.append(“(uid=*)”);
}
LdapConnection connection = LDAPConnectionUtil
.openConnection(connectionParams);

try {

Cursor<SearchResponse> cursor = connection.search(USER_GROUP,
searchQuery.toString(), SearchScope.ONELEVEL, “*”);
while (cursor.next()) {
User user = new UserEntity();
SearchResultEntry response = (SearchResultEntry) cursor.get();
Iterator<EntryAttribute> itEntry = response.getEntry()
.iterator();
while (itEntry.hasNext()) {
EntryAttribute attribute = itEntry.next();
String key = attribute.getId();

if (“uid”.equalsIgnoreCase(key)) {
user.setId(attribute.getString());

} else if (“sn”.equalsIgnoreCase(key)) {
user.setLastName(attribute.getString());

} else if (“cn”.equalsIgnoreCase(key)) {
user.setFirstName(attribute.getString());
}

}

userList.add(user);
}

cursor.close();

} catch (Exception e) {
throw new ActivitiException(“LDAP connection search failure”, e);
}

LDAPConnectionUtil.closeConnection(connection);

return userList;
}

@Override
public long findUserCountByQueryCriteria(UserQueryImpl query) {

return findUserByQueryCriteria(query, null).size();
}

@Override
public Boolean checkPassword(String userId, String password) {

boolean credentialsValid = false;
LdapConnection connection = new LdapConnection(
connectionParams.getLdapServer(),
connectionParams.getLdapPort());
try {
BindResponse response = connection.bind(“uid=” + userId + “,”
+ USER_GROUP, password);

if (response.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS) {
credentialsValid = true;
}
} catch (Exception e) {
throw new ActivitiException(“LDAP connection bind failure”, e);
}

LDAPConnectionUtil.closeConnection(connection);

return credentialsValid;
}
}

d) Create LDAPGroupManagerFactory class

public class LDAPGroupManagerFactory implements SessionFactory {

private LDAPConnectionParams connectionParams;

public LDAPGroupManagerFactory(LDAPConnectionParams params) {
this.connectionParams = params;
}

@Override
public Class<?> getSessionType() {
return GroupManager.class;
}

@Override
public Session openSession() {
System.out.println(“In LDAPGroupManagerFactory : opening session”);
return new LDAPGroupManager(connectionParams);
}

}

e) Create LDAPGroupManager class for connection and query logic to ldap server

 

public class LDAPGroupManager extends GroupManager {

private static final String USER_ENTRY = “ou=users,ou=system”;
private static final String GROUP_ENTRY = “ou=groups,ou=system”;

private LDAPConnectionParams connectionParams;

public LDAPGroupManager(LDAPConnectionParams params) {
this.connectionParams = params;
}

@Override
public Group createNewGroup(String groupId) {
throw new ActivitiException(“LDAP group manager doesn’t support creating a new group”);
}

@Override
public void insertGroup(Group group) {
throw new ActivitiException(“LDAP group manager doesn’t support inserting a new group”);
}

@Override
public void updateGroup(Group updatedGroup) {
throw new ActivitiException(“LDAP group manager doesn’t support updating a new group”);
}

@Override
public void deleteGroup(String groupId) {
throw new ActivitiException(“LDAP group manager doesn’t support deleting a new group”);
}

@Override
public List<Group> findGroupByQueryCriteria(Object query, Page page) {
List<Group> groupList = new ArrayList<Group>();

// Query is a GroupQueryImpl instance
GroupQueryImpl groupQuery = (GroupQueryImpl) query;
StringBuilder searchQuery = new StringBuilder();
if(StringUtils.isNotEmpty(groupQuery.getId())) {
searchQuery.append(“(cn=”).append(groupQuery.getId()).append(“)”);

} else if(StringUtils.isNotEmpty(groupQuery.getName())) {
searchQuery.append(“(cn=”).append(groupQuery.getName()).append(“)”);

} else if(StringUtils.isNotEmpty(groupQuery.getUserId())) {
searchQuery.append(“(uniqueMember= uid=”).append(groupQuery.getUserId()).append(“,” + USER_ENTRY + “)”);

} else {
searchQuery.append(“(cn=*)”);
}
LdapConnection connection = LDAPConnectionUtil.openConnection(connectionParams);
try {
Cursor<SearchResponse> cursor = connection.search(GROUP_ENTRY, searchQuery.toString(), SearchScope.ONELEVEL, “*”);
while (cursor.next()) {
Group group = new GroupEntity();
SearchResultEntry response = (SearchResultEntry) cursor.get();
Iterator<EntryAttribute> itEntry = response.getEntry().iterator();
while(itEntry.hasNext()) {
EntryAttribute attribute = itEntry.next();
String key = attribute.getId();
if(“cn”.equalsIgnoreCase(key)) {
group.setId(attribute.getString());
group.setName(attribute.getString());
}
}

groupList.add(group);
}

cursor.close();

} catch (Exception e) {
throw new ActivitiException(“LDAP connection search failure”, e);
}

LDAPConnectionUtil.closeConnection(connection);

return groupList;
}

@Override
public long findGroupCountByQueryCriteria(Object query) {
return findGroupByQueryCriteria(query, null).size();
}

@Override
public GroupEntity findGroupById(String groupId) {
throw new ActivitiException(“LDAP group manager doesn’t support finding a group by id”);
}

@Override
public List<Group> findGroupsByUser(String userId) {
List<Group> groupList = new ArrayList<Group>();

LdapConnection connection = LDAPConnectionUtil.openConnection(connectionParams);
try {
Cursor<SearchResponse> cursor = connection.search(GROUP_ENTRY, “(uniqueMember= uid=” + userId
+ “,” + USER_ENTRY + “)”, SearchScope.ONELEVEL, “*”);
while (cursor.next()) {
Group group = new GroupEntity();
SearchResultEntry response = (SearchResultEntry) cursor.get();
Iterator<EntryAttribute> itEntry = response.getEntry().iterator();
while(itEntry.hasNext()) {
EntryAttribute attribute = itEntry.next();
String key = attribute.getId();
if(“cn”.equalsIgnoreCase(key)) {
group.setId(attribute.getString());
group.setName(attribute.getString());
}
}

groupList.add(group);
}

cursor.close();

} catch (Exception e) {
throw new ActivitiException(“LDAP connection search failure”, e);
}

LDAPConnectionUtil.closeConnection(connection);

return groupList;
}
}

f) Activiti Engine configuration for ldap. Configure the following beans in applicationContext.xml available in activiti-explorer project.

<beans xmlns=”http://www.springframework.org/schema/beans&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd”&gt;
<bean id=”processEngineConfiguration”
class=”org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration”>
<property name=”databaseSchemaUpdate” value=”true” />
<property name=”customSessionFactories”>
<list>
<bean class=”org.bpmnwithactiviti.chapter10.ldap.LDAPUserManagerFactory”>
<constructor-arg ref=”ldapConnectionParams” />
</bean>
<bean class=”org.bpmnwithactiviti.chapter10.ldap.LDAPGroupManagerFactory”>
<constructor-arg ref=”ldapConnectionParams” />
</bean>
</list>
</property>
</bean>
<bean id=”ldapConnectionParams”
class=”org.bpmnwithactiviti.chapter10.ldap. LDAPConnectionParams”>
<property name=”ldapServer” value=”localhost” />
<property name=”ldapPort” value=”10389″ />
<property name=”ldapUser”
value=”uid=admin,ou=system” />
<property name=”ldapPassword” value=”secret” />
</bean>
</beans>

2) place the required ldap client jars in activiti-explorer lib folder and start the tomcat server.

3) Login with your ldap userid and password. once login to explorer you will find your assigned groups under Queued tab.

4) Now you can create a business process with user task and assign user task to ldap group. After invoking process the task should be displayed in the ldap group.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

One Response to Managing User Identity using Custom LDAP in Activiti Engine

  1. Ajax says:

    hi, I tried to do all this and able to login with credentials of LDAP user but for later uses like SelectUserField it uses identityService’s createUserQuery and createGroupQuery for querying user and group which further goes to configured mysql rather then LDAP. How can I achieve the same??

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s