Steps to enable Active Directory on Bonita 6.5.X Community

All the info I found about that where too ambiguous, not useful by itself. Something like “make an Authentication Service Implementation by yourself”.
So I searched a lot and found some way to make it working. I write the steps here:
(Disclaimer: Use at your own risk, I’m not responsible for any problem/damage direct or indirect.)

1-Create some admins users on Bonita, with exactly the same samAccountName that you have on your Active Directory.
Once you enable AD/LDAP authentication all your users will validate against the Active Directory. Maybe you can tweak the source code below to allow some privileged accounts to be in local Bonita DB.
So make sure you can connect after you link to AD.

2-Download this source code, save it as “JAASAuthenticationServiceImpl.java”
Disclaimer: The source code isn’t mine, it’s taken from https://github.com/stephanel/BonitaBPM-AuthServices/tree/master/src/in/stephanelep/bonita/auth , with some minor tweaks.
It seems to work.

package org.bonitasoft.engine.authentication.impl;

import java.io.Serializable;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.*;

import org.bonitasoft.engine.authentication.AuthenticationConstants;
import org.bonitasoft.engine.authentication.AuthenticationException;
import org.bonitasoft.engine.authentication.GenericAuthenticationService;
import org.bonitasoft.engine.log.technical.TechnicalLogSeverity;
import org.bonitasoft.engine.log.technical.TechnicalLoggerService;
import org.bonitasoft.engine.sessionaccessor.STenantIdNotSetException;
import org.bonitasoft.engine.sessionaccessor.SessionAccessor;

public class JAASAuthenticationServiceImpl implements GenericAuthenticationService {
private TechnicalLoggerService logger;
private SessionAccessor sessionAccessor;

public JAASAuthenticationServiceImpl(final TechnicalLoggerService logger, final SessionAccessor sessionAccessor) {
	this.logger = logger;
	this.sessionAccessor = sessionAccessor;
	this.logger.log(this.getClass(), TechnicalLogSeverity.DEBUG, "AD/LDAP Initialization");
}

@Override
public String checkUserCredentials(final Map<String, Serializable> credentials) throws AuthenticationException {
	long tenantId;
	LoginContext lc;
	
	final String authUsername = String.valueOf(credentials.get(AuthenticationConstants.BASIC_USERNAME));
	final String authPassword = String.valueOf(credentials.get(AuthenticationConstants.BASIC_PASSWORD));
	
	String username = authUsername;
	
	try {
		tenantId = this.sessionAccessor.getTenantId();			
		lc = new LoginContext("BonitaAuthentication-"+tenantId, new CallbackHandler(){
			public void handle(Callback[] callbacks) {
				for(int i = 0; i < callbacks.length; i++) {
					if(callbacks[i] instanceof NameCallback) {
						NameCallback nc = (NameCallback)callbacks[i];
						nc.setName(authUsername);
					}
					else if(callbacks[i] instanceof PasswordCallback) {
						PasswordCallback pc = (PasswordCallback)callbacks[i];
						pc.setPassword(authPassword.toCharArray());
					}
				}
			}
		});
		
		lc.login();
		
		logger.log(this.getClass(), TechnicalLogSeverity.DEBUG, "AD/LDAP: Auth success for user "+username);
		return username;
	}
	catch (LoginException  e) {
		logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Auth failure for user "+username+": "+e.getMessage());
		throw new AuthenticationException();
	}
	catch (STenantIdNotSetException  e) {
		logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Auth failure for user "+username+": "+e.getMessage());
		throw new AuthenticationException();
	}
	catch(Exception e) {
		logger.log(this.getClass(), TechnicalLogSeverity.ERROR, "AD/LDAP: Unknown exception "+e.getClass().toString()+": "+e.getMessage());
	}
	
	return null; 
}

}

3-Then compile it with javac. IMPORTANT! You must compile it with these parameters:

javac -g:vars -cp bonita-server-6.5.1.jar JAASAuthenticationServiceImpl.java

Without the -g:vars the class won’t work. You must have the bonita-server-6.X.X.jar in the same folder, or correctly target it on the -cp parameter.
I used JDK 6 to compile it, just because I saw original bonitasoft classes used it.

4-Then create a temporary folder structure like this: org\bonitasoft\engine\authentication\impl
And place the compiled JAASAuthenticationServiceImpl.class and JAASAuthenticationServiceImpl$1.class inside the “impl” folder.
Zip the structure, you must have a zip with the same structure as I stated, with the two class files on the impl folder.

5-Rename the zip file to “JAASAuthenticationServiceImpl.jar” and place it on apache-tomcat/webapps/bonita/WEB-INF/lib
You can delete this folder structure, it’s only needed to create the jar with the correct folders that matches the package name.
I attach the compiled jar I used, but I encourage you to compile by yourself, it’s really easy to do (you just need a JDK).
Compiled JAASAuthenticationServiceImpl.jar

With that you can use the official document: http://documentation.bonitasoft.com/active-directoryldap-authentication-0
Just don’t use the class=“com.bonitasoft.engine.authentication.impl.JAASGenericAuthenticationServiceImpl”
You must user class=“org.bonitasoft.engine.authentication.impl.JAASGenericAuthenticationServiceImpl” with an starting org. instead of com. because it’s the package I used on the source code.
You can use the original package name that Stephane used on the source code (and creating the folder structure to comply the package name), I just wanted to keep all auth implementations on the same package

I configured exactly that to enable AD on Apache-Tomcat:
AD_1- On setenv.sh (or setenv.bat in Windows) I enabled this line:

SECURITY_OPTS=“-Djava.security.auth.login.config=${CATALINA_HOME}/conf/jaas-standard.cfg”

mine had a # before, I uncommented it.
And modify the CATALINA_OPS line to add this option:

CATALINA_OPTS=“${CATALINA_OPTS} ${BONITA_HOME} ${SECURITY_OPTS} ${DB_OPTS} ${BTM_OPTS} -Dfile.encoding=UTF-8 -Xshare:auto -Xms2048m -Xmx2048m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError”

Note, the other CATALINA_OPS are dependant on your environment, don’t copy mine. Only add the ${SECURITY_OPTS} after ${BONITA_HOME}
On windows it’s something like that:

set SECURITY_OPTS=“-Djava.security.auth.login.config=%CATALINA_HOME%\conf\jaas-standard.cfg”
set CATALINA_OPTS=%CATALINA_OPTS% %BONITA_HOME% %SECURITY_OPTS% %DB_OPTS% %BTM_OPTS% -Dfile.encoding=UTF-8 -Xshare:auto -Xms1024m -Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError

AD_2- Set contents of ${CATALINA_HOME}/conf/jaas-standard.cfg

BonitaAuthentication-1 {
com.sun.security.auth.module.LdapLoginModule REQUIRED
userProvider=“ldap://dc1.domain.com:389/dc=domain,dc=com”
authIdentity=“{USERNAME}@domain.com
userFilter=“(&(objectClass=user)(samAccountName={USERNAME})(!(userAccountControl:1.2.840.113556.1.4.803:=18)))”
useSSL=false
debug=false;
};

Replace dc1.domain.com with your real domain controller (you can also use an IP). My users login with their logon name, they don’t need to add the @domain.com.
Replace domain.com for your real domain name, both on userProvider and authIdentity.
My userFilter searches only actives user accounts with samAccountName = Bonita username.
I search on the whole AD forest, if you want to narrow the search change the userProvider and add something like:
userProvider=“ldap://dc1.domain.com:389/cn=users,dc=domain,dc=com”
check for the correct use of cn= or ou= I always mix them.

If you have several DC’s, I think you can add redundancy with :

userProvider=“ldap://dc1.domain.com:389/dc=domain,dc=com ldap://dc2.domain.com:389/dc=domain,dc=com”

Note: If your users aren’t allowed to search in AD you must add these two lines inside the BonitaAuthentication-1:

java.naming.security.principal="user@domain.com"
java.naming.security.credentials=“yourpassword”

Use some AD user with delegated privileges to make searches and read person objects, DO NOT USE an administrator AD account.

AD_3- Go to apache-tomcat/bonita/server/tenants//conf/services/
Make a backup of the file: cfg-bonita-authentication-impl.xml , name it cfg-bonita-authentication-impl.xml.backup for example.
Edit cfg-bonita-authentication-impl.xml and write this:

   <bean id="authenticationService" class="org.bonitasoft.engine.authentication.impl.JAASAuthenticationServiceImpl" > 
      <constructor-arg index="0" name="logger" ref="tenantTechnicalLoggerService" />                             
      <constructor-arg index="1" name="sessionAccessor" ref="sessionAccessor" />  
</bean>
AD_4- Restart Tomcat server and watch log files for errors. If something fails check names on config files (names are case sensitives) and use debug=true on jass-standard.cfg file, and restart

It’s answered already, it’s an how-to

Excellent work, thank you,

here is another answer that works:

http://community.bonitasoft.com/answers/ldap-auth-bonita-bpm-community#node-24997

so good

hi , quelqu’un a il testé cette solution avec BonitaCommunity 7.2 ???

is anybody know how to configure kerberos with bonita 7.4.3 subscription edition ?

i will try this

i will try this

I didn’t see that answer!!! I searched for weeks, and google never gives me that link :frowning: They gave me only half baked, old stuff.

I found interesting that approach. Mine is just a replacement of the official one.
But the whole compiling stuff is a bit overwhelming, I don’t want to add the whole Eclipse just for that. I’ll go with the javac -g:vars way, I just create the new java and manually compile it with bonita-server jar.
You should never ever tweak/modify standard java files from Bonita package if it isn’t necessary.
I saw phil.allred to recompile the whole thing just to add the LDAP Authentication. And he used the AuthenticationServiceImpl classname. It’s much easier the approach I did.

Create a new Java file, compile it, make a jar and add it to the lib. Then change the cfg-bonita-authentication-impl.xml to the new class and that’s all. If there is a new bonita version custom classes aren’t affected.
In fact I’d like to use that solution because I think I could use it to create/update LDAP users on Bonita if they don’t exist.
Valid LDAP users doesn’t login if that user doesn’t exist yet on Bonita, and that’s a problem. You need some sync process, but I think I can add that process to the login.
In my scenario that’s better because I won’t have a lot of users using Bonita right now, son I’ll auto-create the users who logon, and not all of them.

So I’ll try to tweak that java to have: LDAP+external config file+sync to Bonita+failover to local users. But with a different classname, I prefer not to override standard Bonita classes.

I also tried to search some SSO (single sign-on) using Krb5 kerberos, but there is so little info about it…

hi,
thank you for the solution
do this work ? any one tried it ?

hi , quelqu’un a il testé cette solution avec BonitaCommunity 7.2 ???

Hello,
DrakunDry : do you manage to configure sso with the Community 7.2 version ?

not yet and you ? or you’re in your side

Bonjour,

avez-vous testé cette solution sur la version 7 ?